useRecordContext
useRecordContext
grabs the current record. It’s available anywhere react-admin manipulates a record, e.g. in a Show page, in a Datagrid row, or in a Reference Field.
Usage
The most common use case for useRecordContext
is to build a custom field. For instance, an author field for a book Show view.
import { useRecordContext, Show, SimpleShowLayout } from 'react-admin';
const BookAuthor = () => {
const record = useRecordContext();
if (!record) return null;
return <span>{record.author}</span>;
};
const BookShow = () => (
<Show>
<SimpleShowLayout>
<BookAuthor />
...
</SimpleShowLayout>
</Show>
)
Optimistic Rendering
As react-admin uses optimistic rendering, useRecordContext
may be undefined
or a cached version of the record on load (see also Caching). Make sure you prepare for that!
const BookAuthor = () => {
const record = useRecordContext();
// warning: this will fail on load since record is undefined
return <span>{record.author}</span>;
};
So make sure you check that the record is defined before using it.
const record = useRecordContext();
if (!record) return null;
Availability
As soon as there is a record available, react-admin puts it in a RecordContext
. This means that useRecordContext
works out of the box:
- in descendants of the
<Show>
and<ShowBase>
component - in descendants of the
<Edit>
and<EditBase>
component - in descendants of the
<Create>
and<CreateBase>
component - in descendants of the
<Datagrid>
component - in descendants of the
<SimpleList>
component - in descendants of the
<ReferenceField>
component
Inside A Form
Inside <Edit>
and <Create>
, useRecordContext
returns the initial record, used to set the initial form values.
If you want to react to the data entered by the user, use react-hook-form’s useWatch
instead of useRecordContext
. It returns the current form values, including the changes made by the user.
For instance if you want to display an additional input when a user marks an order as returned, you can do the following:
import { Edit, SimpleForm, BooleanInput, TextInput } from 'react-admin';
import { useWatch } from 'react-hook-form';
const ReturnedReason = () => {
const isReturned = useWatch({ name: 'returned' });
return isReturned ? <TextInput source="reason" /> : null;
};
const OrderEdit = () => (
<Edit>
<SimpleForm>
<TextInput source="reference" />
<BooleanInput source="returned" />
<ReturnedReason />
...
</SimpleForm>
</Edit>
)
Creating a Record Context
If you have fetched a record
and you want to make it available to descendants, place it inside a <RecordContextProvider>
component.
import { useGetOne, RecordContextProvider } from 'react-admin';
const RecordFetcher = ({ id, resource, children }) => {
const { data, isLoading, error } = useGetOne(resource, { id });
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<RecordContextProvider value={data}>
{children}
</RecordContextProvider>
);
};
Fallback Mode
Some react-admin components accept an optional record prop. These components can be used both inside a RecordContext
, and with a custom record prop - without creating a custom record context.
You can do the same: just accept a record
component prop, and pass the props as parameter to the hook. If the record is undefined, useRecordContext
will return the record from the context. If it is defined, useRecordContext
will return the record from the props.
const BookAuthor = (props) => {
const record = useRecordContext(props);
if (!record) return null;
return <span>{record.author}</span>;
};
// you can now pass a custom record
<BookAuthor record={{ id: 123, author: 'Leo Tolstoy' }}>
TypeScript
The useRecordContext
hook accepts a generic parameter for the record type:
type Book = {
id: number;
author: string;
};
const BookAuthor = () => {
const book = useRecordContext<Book>();
if (!book) return null;
// TypeScript knows that book is of type Book
return <span>{book.author}</span>;
};
See Also
WithRecord
is the render prop version of theuseRecordContext
hook.useListContext
is the equivalent for lists.