Skip to content

<ListIterator>

Use the <ListIterator> component to render a list of records in a custom way. Pass a render function to customize how each record is displayed.

import { ListBase, ListIterator } from 'ra-core';
const MostVisitedPosts = () => (
<ListBase
resource="posts"
sort={{ field: 'views', order: 'DESC' }}
perPage={20}
>
<ul>
<ListIterator
render={record => <li>{record.title} - {record.views}</li>}
/>
</ul>
</ListBase>
);

You can use <ListIterator> as a child of any component that provides a ListContext, such as:

Tip: Since this is the headless version, you have full control over how to render lists. <ListIterator> is a low-level component that helps you iterate over records while respecting the loading and error states from the ListContext.

Here are all the props you can set on the <ListIterator> component:

PropRequiredTypeDefaultDescription
childrenOptionalReactNode-The content to render for each record
dataOptionalRaRecord[]-The records. Defaults to the data from the ListContext
emptyOptionalReactNodenullThe content to display when there is no data
errorOptionalReactNodenullThe content to display when the data fetching fails
isPendingOptionalboolean-A boolean indicating whether the data is pending. Defaults to the isPending from the ListContext
loadingOptionalReactNodenullThe content to display while the data is loading
renderOptional(record: RaRecord) => ReactNode-A function that returns the content to render for each record
totalOptionalnumber-The total number of records. Defaults to the total from the ListContext

Additional props are passed to react-hook-form’s useForm hook.

If provided, ListIterator will render the children prop once for each record, inside a RecordContext.

import { ListIterator, useRecordContext } from 'ra-core';
const PostList = () => (
<ul>
<ListIterator>
<PostItem />
</ListIterator>
</ul>
);
const PostItem = () => {
const record = useRecordContext();
if (!record) return null;
return <li>{record.title} - {record.views}</li>;
};

Note: You can’t provide both the children and the render props. If both are provided, <ListIterator> will use the render prop.

Although <ListIterator> reads the data from the closest <ListContext>, you may provide it yourself when no such context is available:

import { ListIterator } from 'ra-core';
import { customerSegments } from './customerSegments.json';
const PostList = () => (
<ul>
<ListIterator
data={customerSegments}
total={customerSegments.length}
render={record => <li>{record.name}</li>}
/>
</ul>
);

To provide a custom UI when there is no data, use the empty prop.

import { ListBase, ListIterator } from 'ra-core';
const PostList = () => (
<ul>
<ListIterator
empty={<li>No posts found</li>}
render={record => <li>{record.title} - {record.views}</li>}
/>
</ul>
);

To provide a custom UI when the data fetching fails, use the error prop.

import { ListIterator } from 'ra-core';
const PostList = () => (
<ul>
<ListIterator
error={<li>Error loading posts</li>}
render={record => <li>{record.title} - {record.views}</li>}
/>
</ul>
);

Although <ListIterator> reads the isPending from the closest <ListContext>, you may provide it yourself when no such context is available. This is useful when dealing with data not coming from the dataProvider:

import { ListIterator } from 'ra-core';
import { useQuery } from '@tanstack/react-query';
import { fetchPostAnalytics } from './fetchPostAnalytics';
const DashboardMostVisitedPosts = () => {
const { data, isPending } = useQuery({
queryKey: ['dashboard', 'posts'],
queryFn: fetchPostAnalytics
});
return (
<ul>
<ListIterator
data={data}
isPending={isPending}
render={record => <li>{record.title} - {record.views}</li>}
/>
</ul>
);
}

To provide a custom UI while the data is loading, use the loading prop.

import { ListIterator } from 'ra-core';
const PostList = () => (
<ul>
<ListIterator
loading={<li>Loading posts...</li>}
render={record => <li>{record.title} - {record.views}</li>}
/>
</ul>
);

If provided, ListIterator will call the render prop for each record. This is useful when the components you render need the record data to render themselves, or when you want to pass additional props to the rendered component.

import { ListIterator } from 'ra-core';
const PostList = () => (
<ul>
<ListIterator
render={record => <li>{record.title} - {record.views}</li>}
/>
</ul>
);

Note: You can’t provide both the children and the render props. If both are provided, <ListIterator> will use the render prop.

Although <ListIterator> reads the total from the closest <ListContext>, you may provide it yourself when no such context is available:

import { ListIterator } from 'ra-core';
import { customerSegments } from './customerSegments.json';
const PostList = () => (
<ul>
<ListIterator
data={customerSegments}
total={customerSegments.length}
render={record => <li>{record.name}</li>}
/>
</ul>
);