FAQ

Can I have custom identifiers/primary keys for my resources?

React-admin requires that each resource has an id field to identify it. If your API uses a different name for the primary key, you have to map that name to id in your dataProvider. For instance, to use a field named _id as identifier:

const dataProvider = {
 getList: (resource, params) => {
 const { page, perPage } = params.pagination;
 const { field, order } = params.sort;
 const query = {
 sort: JSON.stringify([field, order]),
 range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
 filter: JSON.stringify(params.filter),
 };
 const url = `${apiUrl}/${resource}?${stringify(query)}`;
 return httpClient(url).then(({ headers, json }) => ({
- data: json,
+ data: json.map(resource => ({ ...resource, id: resource._id }) ),
 total: parseInt(headers.get('content-range').split('/').pop(), 10),
 }));
 },
 getOne: (resource, params) =>
 httpClient(`${apiUrl}/${resource}/${params.id}`).then(({ json }) => ({
- data: json,
+ { ...json, id: json._id },
 })),
 getMany: (resource, params) => {
 const query = {
 filter: JSON.stringify({ id: params.ids }),
 };
 const url = `${apiUrl}/${resource}?${stringify(query)}`;
 return httpClient(url).then(({ json }) => ({ 
- data: json,
+ data: json.map(resource => ({ ...resource, id: resource._id }) ),
 }));
 },
 getManyReference: (resource, params) => {
 const { page, perPage } = params.pagination;
 const { field, order } = params.sort;
 const query = {
 sort: JSON.stringify([field, order]),
 range: JSON.stringify([(page - 1) * perPage, page * perPage - 1]),
 filter: JSON.stringify({
 ...params.filter,
 [params.target]: params.id,
 }),
 };
 const url = `${apiUrl}/${resource}?${stringify(query)}`;
 return httpClient(url).then(({ headers, json }) => ({
- data: json,
+ data: json.map(resource => ({ ...resource, id: resource._id }) ),
 total: parseInt(headers.get('content-range').split('/').pop(), 10),
 }));
 },
 update: (resource, params) =>
 httpClient(`${apiUrl}/${resource}/${params.id}`, {
 method: 'PUT',
 body: JSON.stringify(params.data),
 }).then(({ json }) => ({ 
- data: json,
+ { ...json, id: json._id },
 })),
 updateMany: (resource, params) => {
 const query = {
 filter: JSON.stringify({ id: params.ids}),
 };
 return httpClient(`${apiUrl}/${resource}?${stringify(query)}`, {
 method: 'PUT',
 body: JSON.stringify(params.data),
 }).then(({ json }) => ({ data: json }));
 }
 create: (resource, params) =>
 httpClient(`${apiUrl}/${resource}`, {
 method: 'POST',
 body: JSON.stringify(params.data),
 }).then(({ json }) => ({
- data: { ...params.data, id: json.id },
+ data: { ...params.data, id: json._id },
 })),
 delete: (resource, params) =>
 httpClient(`${apiUrl}/${resource}/${params.id}`, {
 method: 'DELETE',
 }).then(({ json }) => ({ 
- data: json,
+ { ...json, id: json._id },
 })),
 deleteMany: (resource, params) => {
 const query = {
 filter: JSON.stringify({ id: params.ids}),
 };
 return httpClient(`${apiUrl}/${resource}?${stringify(query)}`, {
 method: 'DELETE',
 body: JSON.stringify(params.data),
 }).then(({ json }) => ({ data: json }));
 }
};

I get a warning about unique key for child in array

When displaying a Datagrid component, you get the following warning:

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of DatagridBody.

This is most probably because the resource does not have an id property as expected by react-admin. See the previous FAQ to see how to resolve this: Can I have custom identifiers/primary keys for my resources?

How can I customize forms depending on its inputs values?

Some use cases:

  • Show/hide some inputs if another input has a value
  • Show/hide some inputs if another input has a specific value
  • Show/hide some inputs if the current form value matches specific constraints

For all those cases, you can use the <FormDataConsumer> component.

UI in production build is empty or broken

You have probably specified a version requirement for @mui/material that is incompatible with the one required by react-admin. As a consequence, npm bundled two copies of Material UI in your application, and doesn’t work in that case.

Please align your version requirement with the one of the ra-ui-materialui package.

See this issue for more information.

My Resource is defined but not displayed on the Menu

You may have declared a resource without list prop. But with the default menu, only resources with a list prop are shown.

<Admin>
 <Resource name="reference" create={PostReference} edit={EditReference} />
</Admin>

In order to have a specific resource without list prop listed on the menu, you have to write your own custom menu.

import { Menu } from 'react-admin';
export const MyMenu = () => (
 <Menu>
 <Menu.ResourceItems />
 <Menu.Item to="/reference/create" primaryText="New Reference" />
 </Menu>
);

I get an error about control being null

In a view that contains a form, you may get the following error:

Cannot read properties of null (reading ‘control’)

This is most probably because you have multiple versions of the react-hook-form package installed, one being a direct dependency in your project and the other brought by react-admin.

First, you can run npm list react-hook-form to check if you have duplicate versions.

To dedupe the package you can run npm dedupe react-hook-form or yarn dedupe react-hook-form.

You may also edit the lockfile manually.

Finally, you can use yarn’s resolutions or npm’s overrides in your package.json file:

{"resolutions":{"react-hook-form":"7.54.2"}}

I get an error about a hook that may be used only in the context of a Router component

When using custom routing configurations, you may encounter strange error messages like:

useLocation() may be used only in the context of a <Router> component

or

useNavigate() may be used only in the context of a <Router> component

or

useRoutes() may be used only in the context of a <Router> component

or

useHref() may be used only in the context of a <Router> component.

or

<Route> may be used only in the context of a <Router> component

These errors can happen if you added react-router and/or react-router-dom to your dependencies, and didn’t use the same version as react-admin. In that case, your application has two versions of react-router, and the calls you add can’t see the react-admin routing context.

You can use the npm list react-router and npm list react-router-dom commands to check which versions are installed.

If there are duplicates, you need to make sure to use only the same version as react-admin. You can deduplicate them using yarn’s resolutions or npm’s overrides.

// in packages.json
{
 // ...
 "resolutions": {
 "react-router-dom": "6.7.0",
 "react-router": "6.7.0"
 }
}

This may also happen inside a Remix application. See Setting up react-admin for Remix for instructions to overcome that problem.

AltStyle によって変換されたページ (->オリジナル) /