Skip to content

Commit f3835e9

Browse files
committed
Merge branch 'next' into marmelab/listRenderProp
2 parents 5add7d5 + dcc816b commit f3835e9

36 files changed

+704
-522
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 5.10.0
4+
5+
- Upgraded `@tanstack/react-query` to `5.83.0`. You might have duplicate versions if you already had it in your dependencies. Should you have an error mentioning the `QueryContext`, make sure you only have one version in your package manager lock file.
6+
37
## 5.9.1
48

59
* Fix `<Datagrid>` empty throws error when used in standalone mode ([#10812](https://github.com/marmelab/react-admin/pull/10812)) ([fzaninotto](https://github.com/fzaninotto))

docs/List.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,42 @@ const ProductList = () => (
12021202
)
12031203
```
12041204

1205+
## Enabling Data Fetching Conditionally
1206+
1207+
You might want to allow data to be fetched only when at least some filters have been set. You can leverage TanStack react-query `enabled` option for that. It accepts a function that receives the query as its only parameter. As react-admin always format the `queryKey` as `[ResourceName, DataProviderMethod, DataProviderParams]`, you can check that there is at least a filter in this function:
1208+
1209+
{% raw %}
1210+
```tsx
1211+
export const PostList = () => (
1212+
<List
1213+
filters={postFilter}
1214+
queryOptions={{
1215+
enabled: query => {
1216+
const listParams = query.queryKey[2] as GetListParams;
1217+
return listParams.filter.q?.length > 2;
1218+
}
1219+
}}
1220+
>
1221+
<WithListContext
1222+
render={context =>
1223+
context.filterValues.q?.length > 2 ? (
1224+
<CardContentInner>
1225+
Type a search term to fetch data
1226+
</CardContentInner>
1227+
) : (
1228+
<Datagrid>
1229+
{/* your fields */}
1230+
</Datagrid>
1231+
)
1232+
}
1233+
/>
1234+
</List>
1235+
)
1236+
```
1237+
{% endraw %}
1238+
1239+
**Note**: Notice we display some custom UI when there is no filter. This is because otherwise, users would see the loading UI as Tanstack Query will set the `isPending` property of the underlying query to `true` if the query isn't enabled.
1240+
12051241
## Accessing Extra Response Data
12061242

12071243
If `dataProvider.getList()` returns additional metadata in the response under the `meta` key, you can access it in the list view using the `meta` property of the `ListContext`.

docs/ListBase.md

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,55 +6,81 @@ storybook_path: ra-core-controller-list-listbase--no-auth-provider
66

77
# `<ListBase>`
88

9-
`<ListBase>` is a headless variant of [`<List>`](./List.md). It fetches a list of records from the data provider, puts it in a [`ListContext`](./useListContext.md), and renders its children. Use it to build a custom list layout.
9+
`<ListBase>` is a headless List page component. It fetches a list of records from the data provider, puts it in a [`ListContext`](./useListContext.md), and renders its children. Use it to build a custom list layout.
1010

1111
Contrary to [`<List>`](./List.md), it does not render the page layout, so no title, no actions, no `<Card>`, and no pagination.
1212

1313
`<ListBase>` relies on the [`useListController`](./useListController.md) hook.
1414

1515
## Usage
1616

17-
You can use `ListBase` to create your own custom reusable List component, like this one:
17+
You can use `ListBase` to create your own custom List page component, like this one:
1818

1919
```jsx
2020
import {
21+
DataTable,
2122
ListBase,
22-
Title,
2323
ListToolbar,
24-
Pagination,
2524
DataTable,
25+
Pagination,
26+
Title,
2627
} from 'react-admin';
2728
import { Card } from '@mui/material';
2829

29-
const MyList = ({ children, actions, filters, title, ...props }) => (
30-
<ListBase {...props}>
31-
<Title title={title}/>
30+
const PostList = () => (
31+
<ListBase>
32+
<Title title="Post List"/>
3233
<ListToolbar
33-
filters={filters}
34-
actions={actions}
34+
filters={[
35+
{ source: 'q', label: 'Search', alwaysOn: true },
36+
{ source: 'published', label: 'Published', type: 'boolean' },
37+
]}
3538
/>
3639
<Card>
37-
{children}
40+
<DataTable>
41+
<DataTable.Col source="title" />
42+
<DataTable.Col source="author" />
43+
<DataTable.Col source="published_at" />
44+
</DataTable>
3845
</Card>
3946
<Pagination />
4047
</ListBase>
4148
);
49+
```
4250

51+
Alternatively, you can pass a `render` function prop instead of `children`. This function will receive the `ListContext` as argument.
52+
53+
```jsx
4354
const PostList = () => (
44-
<MyList title="Post List">
45-
<DataTable>
46-
...
47-
</DataTable>
48-
</MyList>
55+
<ListBase render={({ data, total, isPending, error }) => (
56+
<Card>
57+
<Title title="Post List" />
58+
<ListToolbar
59+
filters={[
60+
{ source: 'q', label: 'Search', alwaysOn: true },
61+
{ source: 'published', label: 'Published', type: 'boolean' },
62+
]}
63+
/>
64+
<DataTable>
65+
{data?.map(record => (
66+
<DataTable.Row key={record.id}>
67+
<DataTable.Col source="title" record={record} />
68+
<DataTable.Col source="author" record={record} />
69+
<DataTable.Col source="published_at" record={record} />
70+
</DataTable.Row>
71+
))}
72+
</DataTable>
73+
<Pagination total={total} />
74+
</Card>
75+
)} />
4976
);
5077
```
5178
52-
This custom List component has no aside component - it's up to you to add it in pure React.
53-
5479
## Props
5580
56-
The `<ListBase>` component accepts the same props as [`useListController`](./useListController.md):
81+
The `<ListBase>` component accepts the following props:
5782
83+
* `children`
5884
* [`debounce`](./List.md#debounce)
5985
* [`disableAuthentication`](./List.md#disableauthentication)
6086
* [`disableSyncWithLocation`](./List.md#disablesyncwithlocation)
@@ -63,11 +89,12 @@ The `<ListBase>` component accepts the same props as [`useListController`](./use
6389
* [`filterDefaultValues`](./List.md#filterdefaultvalues)
6490
* [`perPage`](./List.md#perpage)
6591
* [`queryOptions`](./List.md#queryoptions)
92+
* `render`
6693
* [`resource`](./List.md#resource)
6794
* [`sort`](./List.md#sort)
6895
6996
In addition, `<ListBase>` renders its children components inside a `ListContext`. Check [the `<List children>` documentation](./List.md#children) for usage examples.
70-
Alternatively, you can pass a `render` function prop instead of `children`. This function will receive the `ListContext` as argument.
97+
7198
7299
## Security
73100

0 commit comments

Comments
 (0)