react-admin
react-admin copied to clipboard
<ExportButton> doesn't work in any `ListContext`
What you were expecting
<ExportButton> should just work when used as a child of <ArrayField>, <ReferenceManyField>, or <ReferenceArrayField>
What happened instead
The button is rendered, it calls dataProvider.getList(), but does not trigger a file download on the client.
Steps to reproduce:
https://stackblitz.com/edit/github-juchmy?file=src%2Fposts%2FPostEdit.tsx
In the simple example, in the PostEdit.tsx, add an <ExportButton> as child of <ReferenceManyField>:
<ReferenceManyField reference="comments" target="post_id" fullWidth>
<ExportButton />
<Datagrid>
<DateField source="created_at" />
<TextField source="author.name" />
<TextField source="body" />
<EditButton />
</Datagrid>
</ReferenceManyField>
Then browse to a post detail (e.g. https://githubjuchmy-lbmb--8080--9c8944bc.local-credentialless.webcontainer.io/#/posts/1/3) and click on the export button.
Analysis
There are 2 problems:
- Components that implement a
ListContextdon't include a defaultexporterlikeuseListControllerdoes. <ExportButton>starts by callingdataProvider.getList(), which is wrong in many situations. For instance, when used as a child of<ReferenceArrayField>, the entire data is already fetched and should not be refetched.
Solution
- Add support for an
exporterprop in<ArrayField>,<ReferenceArrayField>and<ReferenceManyField>, and pass it down to the controller - Add a default
exportertouseReferenceArrayFieldController,useReferenceManyFieldController, anduseList - Add a new field in
ListContext:async getData() => Record[], that each controller must define according to its internal logic. It should return the entire list data regardless of pagination. - Update
<ExportButton>to use thisgetDataif present in the context instead ofdataProvider.getList
Note that this change should also allow a "Select All" feature (cf #9043)
Environment
- React-admin version: 4.11
- Last version that did not exhibit the issue (if applicable): N/A
- React version: 17
- Browser: Chrome