<ArrayField>

<ArrayField> renders an embedded array of objects.

ArrayField

<ArrayField> creates a ListContext with the field value, and renders its children components - usually iterator components like <Datagrid> or <SingleFieldList>.

Usage

<ArrayField> is ideal for collections of objects, e.g. tags and backlinks in the following post object:

{
    id: 123,
    title: 'Lorem Ipsum Sit Amet',
    tags: [{ name: 'dolor' }, { name: 'sit' }, { name: 'amet' }],
    backlinks: [
        {
            uuid: '34fdf393-f449-4b04-a423-38ad02ae159e',
            date: '2012-08-10T00:00:00.000Z',
            url: 'http://example.com/foo/bar.html',
        },
        {
            uuid: 'd907743a-253d-4ec1-8329-404d4c5e6cf1',
            date: '2012-08-14T00:00:00.000Z',
            url: 'https://blog.johndoe.com/2012/08/12/foobar.html',
        }
    ]
}

Leverage <ArrayField> e.g. in a Show view, to display the tags as a <SingleFieldList> and the backlinks as a <Datagrid>:

import { 
    ArrayField,
    ChipField,
    Datagrid,
    Show,
    SimpleShowLayout,
    SingleFieldList,
    TextField
} from 'react-admin';

const PostShow = () => (
    <Show>
        <SimpleShowLayout>
            <TextField source="title" />
            <ArrayField source="tags">
                <SingleFieldList>
                    <ChipField source="name" size="small" />
                </SingleFieldList>
            </ArrayField>
            <ArrayField source="backlinks">
                <Datagrid bulkActionButtons={false}>
                    <TextField source="uuid" />
                    <TextField source="date" />
                    <TextField source="url" />
                </Datagrid>
            </ArrayField>
        </SimpleShowLayout>
    </Show>
)

Props

Prop Required Type Default Description
children Required ReactNode   The component to render the list.
filter Optional object   The filter to apply to the list.
perPage Optional number 1000 The number of items to display per page.
sort Optional { field, order}   The sort to apply to the list.

<ArrayField> accepts the common field props, except emptyText (use the child empty prop instead).

<ArrayField> relies on useList to filter, paginate, and sort the data, so it accepts the same props.

children

<ArrayField> renders its children component wrapped in a <ListContextProvider>. Commonly used child components are <Datagrid>, <SingleFieldList>, and <SimpleList>.

{/* using SingleFieldList as child */}
<ArrayField source="tags">
    <SingleFieldList>
        <ChipField source="name" />
    </SingleFieldList>
</ArrayField>

{/* using Datagrid as child */}
<ArrayField source="backlinks">
    <Datagrid>
        <TextField source="uuid" />
        <TextField source="date" />
        <TextField source="url" />
    </Datagrid>
</ArrayField>

{/* using SimpleList as child */}
<ArrayField source="backlinks">
    <SimpleList
        primaryText={record => record.url}
        secondaryText={record => record.date}
    />
</ArrayField>

You can also render custom JSX, leveraging the <WithListContext> component:

<ArrayField source="backlinks">
    <WithListContext render={({ data }) => (
        <ul>
            {data.map(backlink => (
                <li key={backlink.id}>{backlink.url}</li>
            ))}
        </ul>
    )} />
</ArrayField>

Or a custom component, leveraging the useListContext hook:

const Backlinks = () => {
    const { data } = useListContext();
    return (
        <ul>
            {data.map(backlink => (
                <li key={backlink.id}>{backlink.url}</li>
            ))}
        </ul>
    );
};

const PostShow = () => (
    <Show>
        <SimpleShowLayout>
            <TextField source="title" />
            <ArrayField source="backlinks">
                <Backlinks />
            </ArrayField>
        </SimpleShowLayout>
    </Show>
)

filter

You can use the filter prop to display only a subset of the items in the array. For instance, to display only the backlinks for a particular day:

<ArrayField source="backlinks" filter={{ date: '2012-08-10T00:00:00.000Z' }}>
    <Datagrid>
        <TextField source="uuid" />
        <TextField source="date" />
        <TextField source="url" />
    </Datagrid>
</ArrayField>

The filtering capabilities are very limited. For instance, there is no “greater than” or “less than” operator. You can only filter on the equality of a field.

perPage

If the value is a large array, and you don’t need to display all the items, you can use the perPage prop to limit the number of items displayed.

As <ArrayField> creates a ListContext, you can use the <Pagination> component to navigate through the items.

import { 
    ArrayField,
    Datagrid,
    Pagination,
    Show,
    SimpleShowLayout,
    TextField
} from 'react-admin';

const PostShow = () => (
    <Show>
        <SimpleShowLayout>
            <TextField source="title" />
            <ArrayField source="backlinks" perPage={5}>
                <Datagrid>
                    <TextField source="uuid" />
                    <TextField source="date" />
                    <TextField source="url" />
                </Datagrid>
                <Pagination />
            </ArrayField>
        </SimpleShowLayout>
    </Show>
);

sort

By default, <ArrayField> displays the items in the order they are stored in the field. You can use the sort prop to change the sort order.

<ArrayField source="tags" sort={{ field: 'name', order: 'ASC' }}>
    <SingleFieldList>
        <ChipField source="name" />
    </SingleFieldList>
</ArrayField>

Using The List Context

<ArrayField> creates a ListContext with the field value, so you can use any of the list context values in its children. This includes callbacks to sort, filter, and select items.

For instance, you can make the chips selectable as follows:

const SelectedChip = () => {
    const { selectedIds, onToggleItem } = useListContext();
    const record = useRecordContext();
    return (
        <ChipField
            source="title"
            clickable
            onClick={() => {
                onToggleItem(record.id);
            }}
            color={selectedIds.includes(record.id) ? 'primary' : 'default'}
        />
    );
};

const PostShow = () => (
    <Show>
        <SimpleShowLayout>
            <TextField source="title" />
            <ArrayField source="tags">
                <SingleFieldList>
                    <SelectedChip />
                </SingleFieldList>
            </ArrayField>
        </SimpleShowLayout>
    </Show>
)

Tip: The selection logic uses the id field for each collection element, so the above example assumes that the tags field contains objects like { id: 123, name: 'bar' }.

Check the useListContext documentation for more information on the list context values.

Rendering An Array Of Strings

If you need to render a custom collection (e.g. an array of tags ['dolor', 'sit', 'amet']), it’s often simpler to write your own component:

import { useRecordContext } from 'react-admin';

const TagsField = () => {
    const record = useRecordContext();
    return (
        <ul>
            {record.tags.map(item => (
                <li key={item.name}>{item.name}</li>
            ))}
        </ul>
    )
};