Skip to content

Commit 9fafcbd

Browse files
committed
Add RecordsIterator documentation.
1 parent 95d2008 commit 9fafcbd

File tree

3 files changed

+406
-0
lines changed

3 files changed

+406
-0
lines changed

docs/RecordsIterator.md

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
---
2+
layout: default
3+
title: "RecordsIterator"
4+
storybook_path: ra-core-controller-list-recordsiterator
5+
---
6+
7+
# `<RecordsIterator>`
8+
9+
Use the `<RecordsIterator>` component to render a list of records in a custom way. Pass a `render` function to customize how each record is displayed. Pass a `data` prop to use it out of a list context.
10+
11+
## Usage
12+
13+
Use `<RecordsIterator>` inside a [`ListContext`](./useListContext.md) to render each record:
14+
15+
{% raw %}
16+
```jsx
17+
import { ListBase, RecordsIterator } from 'react-admin';
18+
19+
const MostVisitedPosts = () => (
20+
<ListBase
21+
resource="posts"
22+
sort={{ field: 'views', order: 'DESC' }}
23+
perPage={20}
24+
>
25+
<ul>
26+
<RecordsIterator
27+
render={record => <li>{record.title} - {record.views}</li>}
28+
/>
29+
</ul>
30+
</ListBase>
31+
);
32+
```
33+
{% endraw %}
34+
35+
You can use `<RecordsIterator>` as a child of any component that provides a [`ListContext`](./useListContext.md), such as:
36+
37+
- [`<List>`](./List.md),
38+
- [`<ListGuesser>`](./ListGuesser.md),
39+
- [`<ListBase>`](./ListBase.md),
40+
- [`<ReferenceArrayField>`](./ReferenceArrayField.md),
41+
- [`<ReferenceManyField>`](./ReferenceManyField.md)
42+
43+
`<RecordsIterator>` expects that data is properly loaded, without error. If you want to handle loading, error, offline and empty states, use properties on the component providing you the list context (like [`<List>`](./List.md), [`<ReferenceArrayField>`](./ReferenceArrayField.md), [`<ReferenceManyField>`](./ReferenceManyField.md)). You can also make use of [`<WithListContext>`](./WithListContext.md) [`loading`](./WithListContext.md#loading), [`errorElement`](./WithListContext.md#errorelement), [`offline`](./WithListContext.md#offline) and [`empty`](./WithListContext.md#empty) props.
44+
45+
{% raw %}
46+
```jsx
47+
import { ListBase, RecordsIterator, WithListContext } from 'react-admin';
48+
49+
const MostVisitedPosts = () => (
50+
<ListBase
51+
resource="posts"
52+
sort={{ field: 'views', order: 'DESC' }}
53+
perPage={20}
54+
>
55+
<WithListContext
56+
loading={<p>Loading...</p>}
57+
errorElement={<p>Something went wrong</p>}
58+
empty={<p>No posts found</p>}
59+
offline={<p>You are offline</p>}
60+
>
61+
<ul>
62+
<RecordsIterator
63+
render={record => <li>{record.title} - {record.views}</li>}
64+
/>
65+
</ul>
66+
</WithListContext>
67+
</ListBase>
68+
);
69+
```
70+
{% endraw %}
71+
72+
## Props
73+
74+
`<RecordsIterator>` exposes the following important props:
75+
76+
| Prop | Required | Type | Default | Description |
77+
| ----------- | -------- |-----------------------------------| ------- | ---------------------------------------------------------------------------------------------------- |
78+
| `children` | Optional | `ReactNode` | - | The content to render for each record |
79+
| `data` | Optional | `RaRecord[]` | - | The records. Defaults to the `data` from the [`ListContext`](./useListContext.md) |
80+
| `isPending` | Optional | `boolean` | - | A boolean indicating whether the data is pending. Defaults to the `isPending` from the [`ListContext`](./useListContext.md) |
81+
| `render` | Optional | `(record: RaRecord) => ReactNode` | - | A function that returns the content to render for each record |
82+
| `total` | Optional | `number` | - | The total number of records. Defaults to the `total` from the [`ListContext`](./useListContext.md) |
83+
84+
Either `children` or `render` is required.
85+
86+
## `children`
87+
88+
If provided, `RecordsIterator` will render the `children` prop once for each record, inside a [`RecordContext`](./useRecordContext.md).
89+
90+
{% raw %}
91+
```tsx
92+
import { RecordsIterator, useRecordContext } from 'react-admin';
93+
94+
const PostList = () => (
95+
<ul>
96+
<RecordsIterator>
97+
<PostItem />
98+
</RecordsIterator>
99+
</ul>
100+
);
101+
102+
const PostItem = () => {
103+
const record = useRecordContext();
104+
if (!record) return null;
105+
return <li>{record.title} - {record.views}</li>;
106+
};
107+
```
108+
{% endraw %}
109+
110+
**Note**: You can't provide both the `children` and the `render` props. If both are provided, `<RecordsIterator>` will use the `render` prop.
111+
112+
This is useful for advanced scenarios where you need direct access to the record data or want to implement custom layouts.
113+
114+
## `data`
115+
116+
Although `<RecordsIterator>` reads the data from the closest [`<ListContext>`](./useListContext.md), you may provide it yourself when no such context is available:
117+
118+
{% raw %}
119+
```jsx
120+
import { RecordsIterator, TextField } from 'react-admin';
121+
import { customerSegments } from './customerSegments.json';
122+
123+
const PostList = () => (
124+
<ul>
125+
<RecordsIterator
126+
data={customerSegments}
127+
total={customerSegments.length}
128+
>
129+
<li>
130+
<TextField source="name" />
131+
</li>
132+
</RecordsIterator>
133+
</ul>
134+
);
135+
```
136+
{% endraw %}
137+
138+
## `isPending`
139+
140+
Although `<RecordsIterator>` reads the `isPending` from the closest [`<ListContext>`](./useListContext.md), you may provide it yourself when no such context is available. This is useful when dealing with data not coming from the `dataProvider`:
141+
142+
{% raw %}
143+
```tsx
144+
import { RecordsIterator } from 'react-admin';
145+
import { useQuery } from '@tanstack/react-query';
146+
import { fetchPostAnalytics } from './fetchPostAnalytics';
147+
148+
const DashboardMostVisitedPosts = () => {
149+
const { data, isPending } = useQuery({
150+
queryKey: ['dashboard', 'posts'],
151+
queryFn: fetchPostAnalytics
152+
});
153+
154+
return (
155+
<ul>
156+
<RecordsIterator
157+
data={data}
158+
isPending={isPending}
159+
render={record => <li>{record.title} - {record.views}</li>}
160+
/>
161+
</ul>
162+
);
163+
}
164+
```
165+
{% endraw %}
166+
167+
## `render`
168+
169+
If provided, `RecordsIterator` 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.
170+
171+
{% raw %}
172+
```tsx
173+
import { ListBase, RecordsIterator } from 'react-admin';
174+
175+
const PostList = () => (
176+
<ListBase resource="posts">
177+
<ul>
178+
<RecordsIterator
179+
render={record => <li>{record.title} - {record.views}</li>}
180+
/>
181+
</ul>
182+
</ListBase>
183+
);
184+
```
185+
{% endraw %}
186+
187+
**Note**: You can't provide both the `children` and the `render` props. If both are provided, `<RecordsIterator>` will use the `render` prop.
188+
189+
## `total`
190+
191+
Although `<RecordsIterator>` reads the total from the closest [`<ListContext>`](./useListContext), you may provide it yourself when no such context is available:
192+
193+
{% raw %}
194+
```jsx
195+
import { RecordsIterator, TextField } from 'react-admin';
196+
import { customerSegments } from './customerSegments.json';
197+
198+
const PostList = () => (
199+
<ul>
200+
<RecordsIterator
201+
data={customerSegments}
202+
total={customerSegments.length}
203+
>
204+
<li>
205+
<TextField source="name" />
206+
</li>
207+
</RecordsIterator>
208+
</ul>
209+
);
210+
```
211+
{% endraw %}

docs_headless/astro.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export default defineConfig({
110110
'filteringtutorial',
111111
'listbase',
112112
'infinitelistbase',
113+
'recordsiterator',
113114
'filterliveform',
114115
'withlistcontext',
115116
'uselist',

0 commit comments

Comments
 (0)