I'm trying to upgrade a custom app from admin-on-rest to react-admin (v2.15). After I figured out that the declareResources action was "replaced" by registerResource most seemed ok, but I still struggle with the List and Edit components route definitions that complains about missing required props (compared to what props are defined in the custom app documentation).
If I define a List component like this it works fine:
<Route exact path="/mystuffs" render={(routeProps) => <MystuffList hasCreate hasEdit hasShow={false} hasList resource="mystuffs" basePath="/mystuffs" {...routeProps} />} />
Similar the only way I can get an Edit-component to work is to pass the required props like so:
<Route exact path="/mystuffs/:id" render={(routeProps) => <MystuffEdit resource="mystuffs" id={routeProps.match.params.id} basePath="/mystuffs" {...routeProps} />} />
But to me it seems a bit tedious to define all of these props (i.e was not required with admin-on-rest). Is this the correct way of doing it or am I missing something obvious here since the custom app documentation doesn't specify all of the required props?
I ended up adding a custom resource component that is pretty similar to the Resource in react-admin. Something like this:
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import { Switch, Route } from 'react-router-dom';
const RACustomResource = ({ resource, list, edit, create, show, path, children, ...rest }) => {
const { computedMatch, ...options } = rest;
const listResource = list ?
(<Route
exact
path={path}
render={(routeProps) => {
const { staticContext, ...routeOpts } = routeProps;
return React.createElement(list, {
basePath: path || routeProps.match.url,
resource,
hasCreate: !!create,
hasList: !!list,
hasEdit: !!edit,
hasShow: !!show,
...routeOpts,
...options,
});
}}
/>)
: null;
const createResource = create ?
(<Route
path={`${path}/create`}
render={(routeProps) => {
const { staticContext, ...routeOpts } = routeProps;
return React.createElement(create, {
basePath: path || routeProps.match.url,
resource,
hasList: !!list,
hasShow: !!show,
record: {},
...routeOpts,
...options,
});
}}
/>)
: null;
const editResource = edit ?
(<Route
exact
path={`${path}/:id`}
render={(routeProps) => {
const { staticContext, ...routeOpts } = routeProps;
return React.createElement(edit, {
basePath: path || routeProps.match.url,
resource,
hasCreate: !!create,
hasList: !!list,
hasEdit: !!edit,
hasShow: !!show,
id: routeProps.match.params.id,
...routeOpts,
...options,
});
}}
/>)
: null;
const showResource = show ?
(<Route
exact
path={`${path}/:id/show`}
render={(routeProps) => {
const { staticContext, ...routeOpts } = routeProps;
return React.createElement(show, {
basePath: path || routeProps.match.url,
resource,
hasCreate: !!create,
hasList: !!list,
hasEdit: !!edit,
hasShow: !!show,
id: routeProps.match.params.id,
...routeOpts,
...options,
});
}}
/>)
: null;
return (
<Switch>
{createResource}
{showResource}
{editResource}
{listResource}
{children}
</Switch>
);
};
RACustomResource.propTypes = {
resource: PropTypes.string.isRequired,
path: PropTypes.string,
basePath: PropTypes.string,
children: PropTypes.any,
list: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
create: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
edit: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
show: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
};
export default RACustomResource;
// used like this
// <RACustomResource path="/myresource" resource="myresource" list={MyResourceList} create={MyResourceCreate} edit={MyResourceEdit} />
It is indeed required. We have still a lot of work to do on the custom app side, including documentation.
You can help us! Can you explain why you needed to use react-admin this way? What wasn't possible using the default Admin? etc.
Thanks!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With