<ReferenceField>
<ReferenceField>
is useful for displaying many-to-one and one-to-one relationships, e.g. the details of a user when rendering a post authored by that user.
For instance, let’s consider a model where a post
has one author from the users
resource, referenced by a user_id
field.
┌──────────────┐ ┌────────────────┐
│ posts │ │ users │
│--------------│ │----------------│
│ id │ ┌───│ id │
│ user_id │╾──┘ │ name │
│ title │ │ date_of_birth │
│ published_at │ └────────────────┘
└──────────────┘
In that case, use <ReferenceField>
to display the post author’s id as follows:
<ReferenceField source="user_id" reference="users" />
<ReferenceField>
fetches the data, puts it in a RecordContext
, and renders the recordRepresentation
(the record id
field by default).
So it’s a good idea to configure the <Resource recordRepresentation>
to render related records in a meaningul way. For instance, for the users
resource, if you want the <ReferenceField>
to display the full name of the author:
<Resource name="users" list={UserList} recordRepresentation={(record) => `${record.first_name} ${record.last_name}`} />
Alternately, if you pass a child component, <ReferenceField>
will render it instead of the recordRepresentation
. Usual child components for <ReferenceField>
are other <Field>
components (e.g. <TextField>
).
<ReferenceField source="user_id" reference="users">
<TextField source="name" />
</ReferenceField>
This component fetches a referenced record (users
in this example) using the dataProvider.getMany()
method, and passes it to its child.
It uses dataProvider.getMany()
instead of dataProvider.getOne()
for performance reasons. When using several <ReferenceField>
in the same page (e.g. in a <Datagrid>
), this allows to call the dataProvider
once instead of once per row.
Usage
Here is how to render both a post and the author name in a show view:
import { Show, SimpleShowLayout, ReferenceField, TextField, DateField } from 'react-admin';
export const PostShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="title" />
<DateField source="published_at" />
<ReferenceField label="Author" source="user_id" reference="users" />
</SimpleShowLayout>
</Show>
);
With this configuration, <ReferenceField>
wraps the user’s name in a link to the related user <Edit>
page.
Props
Prop | Required | Type | Default | Description |
---|---|---|---|---|
source |
Required | string |
- | Name of the property to display |
reference |
Required | string |
- | The name of the resource for the referenced records, e.g. ‘posts’ |
children |
Optional | ReactNode |
- | One or more Field elements used to render the referenced record |
emptyText |
Optional | string |
’’ | Defines a text to be shown when the field has no value or when the reference is missing |
label |
Optional | string | Function |
resources. [resource]. fields.[source] |
Label to use for the field when rendered in layout components |
link |
Optional | string | Function |
edit |
Target of the link wrapping the rendered child. Set to false to disable the link. |
queryOptions |
Optional | UseQuery Options |
{} |
react-query client options |
sortBy |
Optional | string | Function |
source |
Name of the field to use for sorting when used in a Datagrid |
<ReferenceField>
also accepts the common field props.
emptyText
<ReferenceField>
can display a custom message when the referenced record is missing, thanks to the emptyText
prop.
<ReferenceField source="user_id" reference="users" emptyText="Missing user" />
<ReferenceField>
renders the emptyText
:
- when the referenced record is missing (no record in the
users
table with the rightuser_id
), or - when the field is empty (no
user_id
in the record).
label
By default, <SimpleShowLayout>
, <Datagrid>
and other layout components infer the label of a field based on its source
. For a <ReferenceField>
, this may not be what you expect:
{/* default label is 'User Id', or the translation of 'resources.posts.fields.user_id' if it exists */}
<ReferenceField source="user_id" reference="users" />
That’s why you often need to set an explicit label
on a <ReferenceField>
:
<ReferenceField label="Author name" source="user_id" reference="users" />
React-admin uses the i18n system to translate the label, so you can use translation keys to have one label for each language supported by the interface:
<ReferenceField label="resources.posts.fields.author" source="user_id" reference="users" />
link
To change the link from the <Edit>
page to the <Show>
page, set the link
prop to “show”.
<ReferenceField source="user_id" reference="users" link="show" />
You can also prevent <ReferenceField>
from adding a link to children by setting link
to false
.
// No link
<ReferenceField source="user_id" reference="users" link={false} />
You can also use a custom link
function to get a custom path for the children. This function must accept record
and reference
as arguments.
// Custom path
<ReferenceField
source="user_id"
reference="users"
link={(record, reference) => `/my/path/to/${reference}/${record.id}`}
/>
queryOptions
Use the queryOptions
prop to pass options to the dataProvider.getMany()
query that fetches the referenced record.
For instance, to pass a custom meta
:
<ReferenceField
source="user_id"
reference="users"
queryOptions={{ meta: { foo: 'bar' } }}
>
<TextField source="name" />
</ReferenceField>
reference
The resource to fetch for the related record.
For instance, if the posts
resource has a user_id
field, set the reference
to users
to fetch the user related to each post.
<ReferenceField source="user_id" reference="users" />
sortBy
By default, when used in a <Datagrid>
, and when the user clicks on the column header of a <ReferenceField>
, react-admin sorts the list by the field source
. To specify another field name to sort by, set the sortBy
prop.
<ReferenceField source="user_id" reference="users" sortBy="user.name" />
sx
: CSS API
The <ReferenceField>
component accepts the usual className
prop. You can also override many styles of the inner components thanks to the sx
property (see the sx
documentation for syntax and examples). This property accepts the following subclasses:
Rule name | Description |
---|---|
& .RaReferenceField-link |
Applied to each child element |
To override the style of all instances of <ReferenceField>
using the application-wide style overrides, use the RaReferenceField
key.
Performance
When used in a <Datagrid>
, <ReferenceField>
fetches the referenced record only once for the entire table.
For instance, with this code:
import { List, Datagrid, ReferenceField, TextField, EditButton } from 'react-admin';
export const PostList = () => (
<List>
<Datagrid>
<TextField source="id" />
<ReferenceField label="User" source="user_id" reference="users" />
<TextField source="title" />
<EditButton />
</Datagrid>
</List>
);
React-admin accumulates and deduplicates the ids of the referenced records to make one dataProvider.getMany()
call for the entire list, instead of n dataProvider.getOne()
calls. So for instance, if the API returns the following list of posts:
[
{
id: 123,
title: 'Totally agree',
user_id: 789,
},
{
id: 124,
title: 'You are right my friend',
user_id: 789
},
{
id: 125,
title: 'Not sure about this one',
user_id: 735
}
]
Then react-admin renders the <PostList>
with a loader for the <ReferenceField>
, fetches the API for the related users in one call (dataProvider.getMany('users', { ids: [789,735] }
), and re-renders the list once the data arrives. This accelerates the rendering and minimizes network load.
Rendering More Than One Field
You often need to render more than one field of the reference table (e.g. if the users
table has a first_name
and a last_name
field).
Given that <ReferenceField>
can accept more than one child, you can use as many <Field>
as you like:
import { Show, SimpleShowLayout, ReferenceField, TextField, DateField, FunctionField } from 'react-admin';
export const PostShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="title" />
<DateField source="published_at" />
<ReferenceField label="Author" source="user_id" reference="users">
<TextField source="first_name" />{' '}
<TextField source="last_name" />
</ReferenceField>
</SimpleShowLayout>
</Show>
);
You can also use several <ReferenceField>
for the same resource in a given view - react-admin will deduplicate them and only make one call to the distant table. This is useful e.g. is you want to have one label per field:
import { Show, SimpleShowLayout, ReferenceField, TextField, DateField } from 'react-admin';
export const PostShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="title" />
<DateField source="published_at" />
<ReferenceField label="First name" source="user_id" reference="users">
<TextField source="first_name" />
</ReferenceField>
<ReferenceField label="Last name" source="user_id" reference="users">
<TextField source="last_name" />
</ReferenceField>
</SimpleShowLayout>
</Show>
);
You can also use a <FunctionField>
to render a string composed of several fields.
import { Show, SimpleShowLayout, ReferenceField, TextField, DateField, FunctionField } from 'react-admin';
export const PostShow = () => (
<Show>
<SimpleShowLayout>
<TextField source="id" />
<TextField source="title" />
<DateField source="published_at" />
<ReferenceField label="Name" source="user_id" reference="users">
<FunctionField render={record => `${record.first_name} ${record.last_name}`} />
</ReferenceField>
</SimpleShowLayout>
</Show>
);
Removing The Link
You can prevent <ReferenceField>
from adding a link to its children by setting link
to false
.
// No link
<ReferenceField source="user_id" reference="users" link={false} />