Skip to content

Commit 9c0a9b5

Browse files
committed
Add documentation
1 parent fb15d48 commit 9c0a9b5

File tree

3 files changed

+252
-6
lines changed

3 files changed

+252
-6
lines changed

.lintstagedrc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
{
22
"*.{js,jsx,ts,tsx}": [
3-
"eslint --fix",
4-
"git add",
3+
"eslint --fix"
54
],
65
"*.{json,css,md}": [
7-
"prettier",
8-
"git add"
6+
"prettier"
97
]
108
}

docs/ListIterator.md

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
---
2+
layout: default
3+
title: "ListIterator"
4+
storybook_path: react-admin-admin--basic
5+
---
6+
7+
# `<ListIterator>`
8+
9+
## Usage
10+
11+
Use the `<ListIterator>` component as a child of any component that provides a [`ListContext`](./useListContext.md):
12+
13+
- `<List>`,
14+
- `<ListGuesser>`,
15+
- `<ListBase>`,
16+
- `<ReferenceArrayField>`,
17+
- `<ReferenceManyField>`
18+
19+
{% raw %}
20+
```jsx
21+
import { ListBase, ListIterator } from 'react-admin';
22+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
23+
24+
const DashboardMostVisitedPosts = () => (
25+
<ListBase resource="posts" sort={{ field: 'views', order: 'DESC' }} page={1} perPage={20}>
26+
<OrderedList>
27+
<ListIterator
28+
render={record => <ListItem>{record.title} - {record.views}</ListItem>}
29+
/>
30+
</OrderedList>
31+
</ListBase>
32+
);
33+
```
34+
{% endraw %}
35+
36+
## Props
37+
38+
Here are all the props you can set on the `<AccordionForm>` component:
39+
40+
| Prop | Required | Type | Default | Description |
41+
| ----------- | -------- | ---------------------------------- | ------- | ---------------------------------------------------------------------------------------------------- |
42+
| `children` | Optional | `ReactNode` | - | The content to render for each record |
43+
| `data` | Optional | `RaRecord[]` | - | The records. Defaults to the `data` from the `ListContext` |
44+
| `empty` | Optional | `ReactNode` | `null` | The content to display when there is no data |
45+
| `isPending` | Optional | `boolean` | - | A boolean indicating whether the data is pending. Defaults to the `isPending` from the `ListContext` |
46+
| `pending` | Optional | `ReactNode` | `null` | The content to display while the data is loading |
47+
| `render` | Optional | `(record: RaRecord) => ReactNode` | - | A function that returns the content to render for each record |
48+
| `resource` | Optional | `string` | - | The resource. Defaults to the `ResourceContext` |
49+
| `total` | Optional | `number` | - | The total number of records. Defaults to the `total` from the `ListContext` |
50+
51+
Additional props are passed to `react-hook-form`'s [`useForm` hook](https://react-hook-form.com/docs/useform).
52+
53+
## `children`
54+
55+
If provided, `ListIterator` will render the `children` prop for each record. This is useful when the components you render leverages the [`RecordContext`](./useRecordContext.md):
56+
57+
{% raw %}
58+
```tsx
59+
import { ListBase, ListIterator, useRecordContext } from 'react-admin';
60+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
61+
62+
const DashboardMostVisitedPosts = () => (
63+
<ListBase resource="posts" sort={{ field: 'views', order: 'DESC' }} page={1} perPage={20}>
64+
<OrderedList>
65+
<ListIterator>
66+
<PostItem />
67+
</ListIterator>
68+
</OrderedList>
69+
</ListBase>
70+
);
71+
72+
const PostItem = () => {
73+
const record = useRecordContext();
74+
if (!record) return null;
75+
76+
return (
77+
<ListItem>{record.title} - {record.views}</ListItem>
78+
);
79+
};
80+
```
81+
{% endraw %}
82+
83+
**Note**: You can't provide both the `children` and the `render` props. If both are provided, `<ListIterator>` will use the `render` prop.
84+
85+
## `data`
86+
87+
Although `<ListIterator>` reads the data from the closest [`<ListContext>`](./useListContext), you may provide it yourself when no such context is available:
88+
89+
{% raw %}
90+
```jsx
91+
import { ListIterator } from 'react-admin';
92+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
93+
import { customerSegments } from './customerSegments.json';
94+
95+
const MyComponent = () => {
96+
return (
97+
<OrderedList>
98+
<ListIterator
99+
data={customerSegments}
100+
total={customerSegments.length}
101+
render={record => <ListItem>{record.name}</ListItem>}
102+
/>
103+
</OrderedList>
104+
);
105+
}
106+
```
107+
{% endraw %}
108+
109+
## `empty`
110+
111+
To provide a custom UI when there is no data, use the `empty` prop.
112+
113+
{% raw %}
114+
```jsx
115+
import { ListBase, ListIterator } from 'react-admin';
116+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
117+
118+
const DashboardMostVisitedPosts = () => (
119+
<ListBase resource="posts" sort={{ field: 'views', order: 'DESC' }} page={1} perPage={20}>
120+
<OrderedList>
121+
<ListIterator
122+
empty={<ListItem>No posts found</ListItem>}
123+
render={record => <ListItem>{record.title} - {record.views}</ListItem>}
124+
/>
125+
</OrderedList>
126+
</ListBase>
127+
);
128+
```
129+
{% endraw %}
130+
131+
## `isPending`
132+
133+
Although `<ListIterator>` reads the `isPending` from the closest [`<ListContext>`](./useListContext), you may provide it yourself when no such context is available. This is useful when dealing with data not coming from the `dataProvider`:
134+
135+
{% raw %}
136+
```tsx
137+
import { ListBase, ListIterator } from 'react-admin';
138+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
139+
import { useQuery } from '@tanstack/react-query';
140+
import { fetchPostAnalytics } from './fetchPostAnalytics';
141+
142+
const DashboardMostVisitedPosts = () => {
143+
const { data, isPending } = useQuery({
144+
queryKey: ['dashboard', 'posts'],
145+
queryFn: fetchPostAnalytics
146+
});
147+
148+
return (
149+
<OrderedList>
150+
<ListIterator
151+
isPending={isPending}
152+
render={record => <ListItem>{record.title} - {record.views}</ListItem>}
153+
/>
154+
</OrderedList>
155+
);
156+
}
157+
```
158+
{% endraw %}
159+
160+
161+
## `pending`
162+
163+
To provide a custom UI while the data is loading use the `pending` prop.
164+
165+
{% raw %}
166+
```jsx
167+
import { ListBase, ListIterator } from 'react-admin';
168+
import { OrderedList, ListItem, Skeleton } from 'my-favorite-ui-lib';
169+
170+
const DashboardMostVisitedPosts = () => (
171+
<ListBase resource="posts" sort={{ field: 'views', order: 'DESC' }} page={1} perPage={20}>
172+
<OrderedList>
173+
<ListIterator
174+
pending={<Skeleton />}
175+
render={record => <ListItem>{record.title} - {record.views}</ListItem>}
176+
/>
177+
</OrderedList>
178+
</ListBase>
179+
);
180+
```
181+
{% endraw %}
182+
183+
## `render`
184+
185+
If provided, `ListIterator` will call the `render` prop for each record. This is useful when the components you render don't leverage the [`RecordContext`](./useRecordContext.md):
186+
187+
{% raw %}
188+
```tsx
189+
import { ListBase, ListIterator } from 'react-admin';
190+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
191+
192+
const DashboardMostVisitedPosts = () => (
193+
<ListBase resource="posts" sort={{ field: 'views', order: 'DESC' }} page={1} perPage={20}>
194+
<OrderedList>
195+
<ListIterator
196+
render={record => <ListItem>{record.title} - {record.views}</ListItem>}
197+
/>
198+
</OrderedList>
199+
</ListBase>
200+
);
201+
```
202+
{% endraw %}
203+
204+
**Note**: You can't provide both the `children` and the `render` props. If both are provided, `<ListIterator>` will use the `render` prop.
205+
206+
## `resource`
207+
208+
Although `<ListIterator>` reads the resource from the closest [`<ResourceContext>`](./Resource.md#resource-context), you may provide it yourself when no such context is available (e.g. in a [dashboard](./Admin.md#dashboard) or a [custom page](./Admin.md#adding-custom-pages)):
209+
210+
{% raw %}
211+
```jsx
212+
import { ListBase, ListIterator } from 'react-admin';
213+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
214+
215+
const DashboardMostVisitedPosts = () => (
216+
<ListBase resource="posts" sort={{ field: 'views', order: 'DESC' }} page={1} perPage={20}>
217+
<OrderedList>
218+
<ListIterator
219+
render={record => <ListItem>{record.title} - {record.views}</ListItem>}
220+
/>
221+
</OrderedList>
222+
</ListBase>
223+
);
224+
```
225+
{% endraw %}
226+
227+
## `total`
228+
229+
Although `<ListIterator>` reads the total from the closest [`<ListContext>`](./useListContext), you may provide it yourself when no such context is available:
230+
231+
{% raw %}
232+
```jsx
233+
import { ListIterator } from 'react-admin';
234+
import { OrderedList, ListItem } from 'my-favorite-ui-lib';
235+
import { customerSegments } from './customerSegments.json';
236+
237+
const MyComponent = () => {
238+
return (
239+
<OrderedList>
240+
<ListIterator
241+
data={customerSegments}
242+
total={customerSegments.length}
243+
render={record => <ListItem>{record.name}</ListItem>}
244+
/>
245+
</OrderedList>
246+
);
247+
}
248+
```
249+
{% endraw %}
250+

packages/ra-core/src/controller/list/ListIterator.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,5 @@ export interface ListIteratorProps<RecordType extends RaRecord = any> {
6262
resource?: string;
6363
data?: RecordType[];
6464
total?: number;
65-
isLoading?: boolean;
6665
isPending?: boolean;
67-
isLoaded?: boolean;
6866
}

0 commit comments

Comments
 (0)