useGetList
This hook calls dataProvider.getList()
when the component mounts. It’s ideal for getting a list of records. It supports filtering, sorting, and pagination.
Syntax
Section titled “Syntax”const { data, total, isPending, error, refetch, meta } = useGetList( resource, { pagination: { page, perPage }, sort: { field, order }, filter, meta }, options);
The meta
argument is optional. It can be anything you want to pass to the data provider, e.g. a list of fields to show in the result. It is distinct from the meta
property of the response, which may contain additional metadata returned by the data provider.
The options
parameter is optional, and is passed to react-query’s useQuery
hook. It may contain the following options:
cacheTime
enabled
initialData
initialDataUpdatedAt
isDataEqual
keepPreviousData
meta
notifyOnChangeProps
notifyOnChangePropsExclusions
onError
onSettled
onSuccess
placeholderData
queryKeyHashFn
refetchInterval
refetchIntervalInBackground
refetchOnMount
refetchOnReconnect
refetchOnWindowFocus
retry
retryOnMount
retryDelay
select
staleTime
structuralSharing
suspense
useErrorBoundary
Check react-query’s useQuery
hook documentation for details on each of these options.
The react-query query key for this hook is [resource, 'getList', { pagination, sort, filter, meta }]
.
Call the useGetList
hook when you need to fetch a list of records from the data provider.
import { useGetList } from 'ra-core';
const LatestNews = () => { const { data, total, isPending, error } = useGetList( 'posts', { pagination: { page: 1, perPage: 10 }, sort: { field: 'published_at', order: 'DESC' } } ); if (isPending) { return <div>Loading...</div>; } if (error) { return <p>ERROR</p>; } return ( <> <h1>Latest news</h1> <ul> {data.map(record => <li key={record.id}>{record.title}</li> )} </ul> <p>{data.length} / {total} articles</p> </> );};
Rendering Data
Section titled “Rendering Data”If you want to use the result in a ra-core iterator component, you must first create a ListContext
with the data. The useList
hook does that for you:
import { useGetList, useList, ListContextProvider,} from 'ra-core';import { DataTable } from './DataTable';import { DateField } from './DateField';import { Pagination } from './Pagination';
const LatestNews = () => { const { data, isPending, error } = useGetList( 'posts', { pagination: { page: 1, perPage: 100 } }, ); if (error) { return <p>ERROR</p>; } const listContext = useList({ data, isPending, perPage: 10, sort: { field: 'published_at', order: 'DESC' } }); return ( <ListContextProvider value={listContext}> <h1>Latest news</h1> <DataTable> <DataTable.Col source="title" /> <DataTable.Col source="published_at" field={DateField} /> <DataTable.NumberCol source="views" /> </DataTable> <Pagination /> </ListContextProvider> );};
In this example, the useGetList
hook fetches all the posts, and displays a list of the 10 most recent posts in a custom layout. The pagination controls allow the user to navigate through the list. Users can also implement sorting by extending the example.
Passing Additional Arguments
Section titled “Passing Additional Arguments”If you need to pass additional arguments to the data provider, you can pass them in the meta
argument.
For example, if you want to embed related records in the response, and your data provider supports the embed
meta parameter, you can pass it like this:
const { data, total, isPending, error } = useGetList( 'posts', { pagination: { page: 1, perPage: 10 }, sort: { field: 'published_at', order: 'DESC' }, // Pass extra parameters using the meta argument meta: { embed: ['author', 'category'] } });
Tip: Don’t mix the meta
parameter with the meta
property of the response (see below). Although they share the same name, they are not related.
Accessing Response Metadata
Section titled “Accessing Response Metadata”If your backend returns additional metadata along with the records, you can access it in the meta
property of the result.
const { data, total, isPending, error, // access the extra response details in the meta property meta} = useGetList('posts', { pagination: { page: 1, perPage: 10 }});
Tip: Don’t mix the meta
property of the response with the meta
parameter (see above). Although they share the same name, they are not related.
Partial Pagination
Section titled “Partial Pagination”If your data provider doesn’t return the total
number of records (see Partial Pagination), you can use the pageInfo
field to determine if there are more records to fetch.
import { useState } from 'react';import { useGetList } from 'ra-core';
const LatestNews = () => { const [page, setPage] = useState(1); const { data, pageInfo, isPending, error } = useGetList( 'posts', { pagination: { page, perPage: 10 }, sort: { field: 'published_at', order: 'DESC' } } ); if (isPending) { return <div>Loading...</div>; } if (error) { return <p>ERROR</p>; } const { hasNextPage, hasPreviousPage } = pageInfo;
const getNextPage = () => setPage(page + 1);
return ( <> <h1>Latest news</h1> <ul> {data.map(record => <li key={record.id}>{record.title}</li> )} </ul> {hasNextPage && <button onClick={getNextPage}>More articles</button>} </> );};
Alternately, you can use the useInfiniteGetList
hook to keep the previous pages on screen while loading new pages - just like users see older content when they scroll down their feed on social media.
Fetching Related Records
Section titled “Fetching Related Records”If you plan on using useGetList
to fetch a list of records related to another one (e.g. the comments for a post), you’re better off using the <ReferenceManyFieldBase>
component. It will handle the data fetching, and empty and loading states for you.
import { ReferenceManyFieldBase } from 'ra-core';
const PostComments = () => { return ( <ReferenceManyFieldBase reference="comments" target="post_id"> <div> {/* Your custom iterator */} </div> </ReferenceManyFieldBase> );};
is the equivalent of:
import { useGetList, useRecordContext, useList, ListContextProvider } from 'ra-core';
const PostComments = () => { const record = useRecordContext(); const { data, isPending, error } = useGetList( 'comments', { filter: { post_id: record.id } } ); const listContext = useList({ data }); if (isPending) { return null; } if (error) { return null; } if (!data || !data.length) { return null; } return ( <ListContextProvider value={listContext}> <div> {/* Your custom iterator */} </div> </ListContextProvider> );};
Refreshing The List
Section titled “Refreshing The List”If you want to refresh the list, you can use the refetch
function returned by the hook:
import { useGetList } from 'ra-core';
const LatestNews = () => { const { data, total, isPending, error, refetch } = useGetList(/* ... */); if (isPending) { return <div>Loading...</div>; } if (error) { return <p>ERROR</p>; } return ( <> <h1>Latest news</h1> <ul> {data.map(record => <li key={record.id}>{record.title}</li> )} </ul> <p>{data.length} / {total} articles</p> <button onClick={() => refetch()}>Refresh</button> </> );};
TypeScript
Section titled “TypeScript”The useGetList
hook accepts a generic parameter for the record type:
import { useGetList } from 'ra-core';
type Post = { id: number; title: string;};
const LatestNews = () => { const { data: posts, total, isPending, error } = useGetList<Post>( 'posts', { pagination: { page: 1, perPage: 10 }, sort: { field: 'published_at', order: 'DESC' } } ); if (isPending) { return <div>Loading...</div>; } if (error) { return <p>ERROR</p>; } return ( <> <h1>Latest news</h1> <ul> {/* TypeScript knows that posts is of type Post[] */} {posts.map(post => <li key={post.id}>{post.title}</li> )} </ul> <p>{posts.length} / {total} articles</p> </> );};