<ShowBase>
<ShowBase>
is a headless variant of <Show>
. It fetches the record from the data provider via dataProvider.getOne()
, puts it in a ShowContext
, and renders its child. Use it to build a custom show page layout.
Contrary to <Show>
, it does not render the page layout, so no title, no actions, and no <Card>
.
<ShowBase>
relies on the useShowController
hook.
Usage
Use <ShowBase>
instead of <Show>
when you want a completely custom page layout, without the default actions and title.
// in src/posts.jsx
import * as React from "react";
import { ShowBase } from 'react-admin';
const PostShow = () => (
<ShowBase resource="posts">
<Grid container>
<Grid item xs={8}>
<SimpleShowLayout>
...
</SimpleShowLayout>
</Grid>
<Grid item xs={4}>
Show instructions...
</Grid>
</Grid>
<div>
Post related links...
</div>
</ShowBase>
);
Components using <ShowBase>
can be used as the show
prop of a <Resource>
component:
// in src/App.jsx
import { Admin, Resource } from 'react-admin';
import { dataProvider } from './dataProvider';
import { PostShow } from './posts';
const App = () => (
<Admin dataProvider={dataProvider}>
<Resource name="posts" show={PostShow} />
</Admin>
);
Tip: See useShowController
for a completely headless version of this component.
Props
Prop | Required | Type | Default | Description |
---|---|---|---|---|
children |
Required | ReactNode |
The components rendering the record fields | |
disable Authentication |
Optional | boolean |
Set to true to disable the authentication check |
|
empty WhileLoading |
Optional | boolean |
Set to true to return null while the list is loading |
|
id |
Optional | string |
The record identifier. If not provided, it will be deduced from the URL | |
queryOptions |
Optional | object |
The options to pass to the useQuery hook |
|
resource |
Optional | string |
The resource name, e.g. posts |
children
<ShowBase>
renders its children wrapped by a RecordContext
, so you can use any component that depends on such a context to be defined - including all Field components.
For instance, to display several fields in a single line, you can use Material UI’s <Grid>
component:
import { ShowBase, TextField, DateField, ReferenceField, WithRecord } from 'react-admin';
import { Grid } from '@mui/material';
import StarIcon from '@mui/icons-material/Star';
const BookShow = () => (
<ShowBase emptyWhileLoading>
<Grid container spacing={2} sx={{ margin: 2 }}>
<Grid item xs={12} sm={6}>
<TextField label="Title" source="title" />
</Grid>
<Grid item xs={12} sm={6}>
<ReferenceField label="Author" source="author_id" reference="authors">
<TextField source="name" />
</ReferenceField>
</Grid>
<Grid item xs={12} sm={6}>
<DateField label="Publication Date" source="published_at" />
</Grid>
<Grid item xs={12} sm={6}>
<WithRecord label="Rating" render={record => <>
{[...Array(record.rating)].map((_, index) => <StarIcon key={index} />)}
</>} />
</Grid>
</Grid>
</ShowBase>
);
disableAuthentication
By default, the <ShowBase>
component will automatically redirect the user to the login page if the user is not authenticated. If you want to disable this behavior and allow anonymous access to a show page, set the disableAuthentication
prop to true
.
const PostShow = () => (
<ShowBase disableAuthentication>
...
</ShowBase>
);
emptyWhileLoading
By default, <ShowBase>
renders its child component even before the dataProvider.getOne()
call returns. If you use <SimpleShowLayout>
or <TabbedShowLayout>
, this isn’t a problem as these components only render when the record has been fetched. But if you use a custom child component that expects the record context to be defined, your component will throw an error.
The <ShowBase emptyWhileLoading>
prop provides a convenient shortcut for that use case. When enabled, <ShowBase>
won’t render its child until the record is loaded.
const BookShow = () => (
<ShowBase emptyWhileLoading>
...
</ShowBase>
);
id
By default, <ShowBase>
deduces the identifier of the record to show from the URL path. So under the /posts/123/show
path, the id
prop will be 123
. You may want to force a different identifier. In this case, pass a custom id
prop.
export const PostShow = () => (
<ShowBase id="123">
...
</ShowBase>
);
Tip: Pass both a custom id
and a custom resource
prop to use <ShowBase>
independently of the current URL. This even allows you to use more than one <ShowBase>
component in the same page.
queryOptions
<ShowBase>
accepts a queryOptions
prop to pass options to the react-query client.
This can be useful e.g. to override the default error side effect. By default, when the dataProvider.getOne()
call fails at the dataProvider level, react-admin shows an error notification and refreshes the page.
You can override this behavior and pass custom side effects by providing a custom queryOptions
prop:
import * as React from 'react';
import { useNotify, useRefresh, useRedirect, ShowBase, SimpleShowLayout } from 'react-admin';
const PostShow = () => {
const notify = useNotify();
const refresh = useRefresh();
const redirect = useRedirect();
const onError = (error) => {
notify(`Could not load post: ${error.message}`, { type: 'error' });
redirect('/posts');
refresh();
};
return (
<ShowBase queryOptions=>
<SimpleShowLayout>
...
</SimpleShowLayout>
</ShowBase>
);
}
The onError
function receives the error from the dataProvider call (dataProvider.getOne()
), which is a JavaScript Error object (see the dataProvider documentation for details).
The default onError
function is:
(error) => {
notify('ra.notification.item_doesnt_exist', { type: 'error' });
redirect('list', resource);
refresh();
}
resource
By default, <ShowBase>
operates on the current ResourceContext
(defined at the routing level), so under the /posts/1/show
path, the resource
prop will be posts
. You may want to force a different resource. In this case, pass a custom resource
prop, and it will override the ResourceContext
value.
export const UsersShow = () => (
<ShowBase resource="users">
...
</ShowBase>
);
Tip: Pass both a custom id
and a custom resource
prop to use <ShowBase>
independently of the current URL. This even allows you to use more than one <ShowBase>
component in the same page.