<RecordField>

<RecordField> displays a label and a record property.

RecordField

Usage

Use <RecordField> as descendent of a RecordContextProvider like in record detail components (<Show>, <Edit>, <ReferenceField>, <ReferenceOneField>).

For instance, to render the title of a book in a show view:

import { Show, RecordField } from 'react-admin';
import { Stack } from '@mui/material';

export const BookShow = () => (
    <Show>
        <Stack>
            <RecordField source="title" />
        </Stack>
    </Show>
);

<RecordField> renders a label based on the humanized source prop, or on the label prop if present. It also grabs the record from the current RecordContext, extracts the record[source] property, and displays it using a <TextField> by default.

You can override the label by passing a label prop:

<RecordField source="title" label="Book title" />

The source prop can be a deep source:

<RecordField label="Author name" source="author.name" />

You can customize the way the value is displayed by passing a Field component in the field prop. For example, to display a numeric value using the browser locale, use the NumberField:

import { RecordField, NumberField } from 'react-admin';

<RecordField source="price" field={NumberField} />

If you need to pass specific props to the field component, for example to format the value, prefer passing a field component as child. In this case, the source passed to the RecordField will only be used for the label:

import { RecordField, NumberField } from 'react-admin';

<RecordField source="price">
    <NumberField source="price" options={{ style: 'currency', currency: 'USD' }} />
</RecordField>

If you need to aggregate multiple fields, you can use the render prop instead, to pass a function that receives the current record and returns a React element:

import { RecordField } from 'react-admin';

<RecordField
    label="Name"
    render={record => `${record.firstName} ${record.lastName}`}
/>

The field, children, and render props are mutually exclusive.

Props

Prop Required Type Default Description
children Optional ReactNode ’’ Elements rendering the actual field.
className Optional string ’’ CSS class name to apply to the field.
empty Optional ReactNode ’’ Text to display when the field is empty.
field Optional ReactElement TextField Field component used to render the field. Ignored if children or render are set.
label Optional string ’’ Label to render. Can be a translation key.
record Optional object {} Record to use. If not set, the record is taken from the context.
render Optional record => JSX   Function to render the field value. Ignored if children is set.
source Optional string ’’ Name of the record field to render.
sx Optional object {} Styles to apply to the field.
TypographyProps Optional object {} Props to pass to label wrapper
variant Optional 'default' || 'inline' ‘default’ When inline, the label is displayed inline with the field value.

children

The children prop is used to pass a field component that will be rendered instead of the default one. The source prop will only be used for the label.

import { RecordField, NumberField } from 'react-admin';

<RecordField source="price">
    <NumberField source="price" options={{ style: 'currency', currency: 'USD' }} />
</RecordField>

This ability is often used to render a field from a reference record, using <ReferenceField>:

import { RecordField, ReferenceField } from 'react-admin';

<RecordField label="Author">
    <ReferenceField source="author_id" reference="users" />
</RecordField>

If you just need to use a field component without any special prop, prefer the field prop:

import { RecordField, NumberField } from 'react-admin';

<RecordField source="price" field={NumberField} />
// instead of
<RecordField source="price">
    <NumberField source="price" />
</RecordField>

empty

When the record contains no value for the source prop, RecordField renders an empty string. If you need to render a custom string in this case, you can use the empty prop :

<RecordField source="title" empty="Missing title" />

empty also accepts a translation key, so you can have a localized string when the field is empty:

<RecordField source="title" empty="resources.books.fields.title.missing" />

If you use the render prop, you can even use a React element as empty value.

<RecordField
    source="title"
    empty={<span style={{ color: 'red' }}>Missing title</span>}
    render={record => record.title}
/>

Note that empty is ignored when you pass a custom field component as child. In this case, it’s the child’s responsibility to handle the empty value.

<RecordField label="title">
    <TextField source="title" emptyText="Missing title" />
</RecordField>

field

By default, <RecordField> uses the <TextField> component to render the field value.

<RecordField source="title" />
// equivalent to
<RecordField source="title" field={TextField} />

Use the field prop to pass a custom field component instead:

import { RecordField, NumberField } from 'react-admin';

<RecordField source="price" field={NumberField} />

If you need to pass specific props to the field component, for example to format the value, prefer passing a field component as child. In this case, the source passed to the RecordField will only be used for the label:

import { RecordField, NumberField } from 'react-admin';

<RecordField source="price">
    <NumberField source="price" options={{ style: 'currency', currency: 'USD' }} />
</RecordField>

label

When you use the source prop, the label is automatically generated from the source name using the “humanize” function. For example, the source author.name will be displayed as “Author name”.

You can customize the label by passing a custom translation for the resources.${resourceName}.fields.${source} key. For example, if you have a resource called posts, and you want to customize the label for <RecordField source="title" /> field, you can add the following translation:

{
    "resources": {
        "posts": {
            "fields": {
                "title": "Post title"
            }
        }
    }
}

If you don’t use the source prop, or if you don’t want to use the i18N features to customize the label, you can use the label prop to override the default label:

<RecordField source="title" label="Post title" />

If you pass a translation key as label, react-admin will use the i18nProvider to translate it:

<RecordField source="title" label="resources.posts.fields.title_custom" />

Finally, you can pass false to the label prop to hide the label:

<RecordField source="title" label={false} />

Note that using label={false} is equivalent to rendering a <TextField> directly.

record

By default, <RecordField> uses the record from the current RecordContext. You can override this behavior by passing a record prop:

<RecordField record={record} source="title" />

render

The render prop is used to pass a function that receives the current record and returns a React element. This is useful when you need to aggregate multiple fields, or when you need to use a component that doesn’t accept the source prop.

import { RecordField } from 'react-admin';

<RecordField
    label="Name"
    render={record => `${record.firstName} ${record.lastName}`}
/>

If you pass both source and render, the source will be used for the label only.

sx

Use the sx prop to pass custom styles to the field.

<RecordField source="id" sx={{ opacity: 0.5 }} />

If you want to style the label, use the TypographyProps prop instead:

<RecordField
    source="id"
    TypographyProps={{ sx: { color: 'red' } }}
/>

If you want to style the value only, prefer passing a custom component as child:

<RecordField source="id">
    <TextField source="id" sx={{ color: 'red' }} />
</RecordField>

source

Use the source prop to specify the name of the record field to render.

For example, if the current record is:

{
    "id": 123,
    "title": "My post",
    "author": {
        "name": "John Doe"
    }
}

To display the title field, use:

<RecordField source="title" />

The source prop can be a deep source, for example author.name.

<RecordField source="author.name" />

If you use the render or children prop, the source will only be used for the label.

TypographyProps

The TypographyProps prop is used to pass props to the label wrapper. This is useful when you want to style the label differently from the field value.

<RecordField
    source="id"
    TypographyProps={{ sx: { color: 'red' } }}
/>

variant

By default, <RecordField> renders the label above the field value. You can use the variant prop to render the label inline with the field value:

<RecordField
    source="title"
    variant="inline"
/>

If you need to customize the width of the label, you can use the TypographyProps prop:

<RecordField
    source="title"
    variant="inline"
    TypographyProps={{ sx: { width: 200 } }}
/>

But since you generally need to do it for several fields, it’s preferable to do it in the parent component:

<Stack sx={{ '& .RaRecordField-label': { width: 200 } }}>
    <RecordField variant="inline" source="id" />
    <RecordField variant="inline" source="title" />
    <RecordField variant="inline" source="author" />
    <RecordField variant="inline" source="summary" />
    <RecordField variant="inline" source="year" field={NumberField} />
</Stack>

Tip: If you want all your fields to be displayed inline, you can define the default variant for RecordField in a custom application Theme:

import { defaultTheme } from 'react-admin';
import { deepmerge } from '@mui/utils';

const theme = deepmerge(defaultTheme, {
    components: {
        RaRecordField: {
            defaultProps: {
                variant: 'inline',
            },
        },
    },
});

const App = () => (
    <Admin theme={theme}>
        // ...
    </Admin>
);

TypeScript

<RecordField> is a generic component. You can pass a type parameter to get hints for the source prop and type safety for the record argument of the render function.

import { Show, RecordField } from 'react-admin';
import { Stack } from '@mui/material';

import { Book } from './types';

const BookShow = () => {
    const BookField = RecordField<Book>;
    return (
        <Show>
            <Stack>
                <BookField source="title" />
                <BookField source="author.name" />
                <BookField source="price" render={record => `${record.price} USD`} />
            </Stack>
        </Show>
    );
};