<ShowBase>

<ShowBase> is a headless component that lets you build custom Show pages. It handles the logic of the Show page:

  • it calls useShowController to fetch the record from the data provider via dataProvider.getOne(),
  • it computes the default page title
  • it creates a ShowContext and a RecordContext,
  • it renders its child component

Contrary to <Show>, it does not render the page layout, so no title, no actions, and no <Card>.

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.