From 295f38d04b7fb99b5ef332f413cad69e21ed0bd4 Mon Sep 17 00:00:00 2001 From: Gildas <1122076+djhi@users.noreply.github.com> Date: Tue, 10 Jun 2025 16:30:27 +0200 Subject: [PATCH] Fix DataTable crashes when its data is not a React primitive --- .../src/list/datatable/DataTable.spec.tsx | 12 +++ .../src/list/datatable/DataTable.stories.tsx | 89 +++++++++++-------- .../src/list/datatable/DataTableCell.tsx | 6 +- 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx b/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx index 5572a40afc1..2eadc6c78b5 100644 --- a/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx +++ b/packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx @@ -10,6 +10,7 @@ import { ExpandSingle, IsRowExpandable, IsRowSelectable, + NonPrimitiveData, } from './DataTable.stories'; describe('DataTable', () => { @@ -34,6 +35,17 @@ describe('DataTable', () => { screen.getByText('Author'); screen.getByText('Year'); }); + it('should render non React primitive data without crashing', async () => { + render(); + await waitFor(() => { + expect(screen.getAllByRole('row')).toHaveLength(6); + }); + screen.getByText('War and Peace'); + screen.getByText('Pride and Prejudice'); + screen.getByText('The Picture of Dorian Gray'); + screen.getByText('Le Petit Prince'); + screen.getByText('The Alchemist'); + }); describe('Sorting', () => { it('should show the default sort column with the default sort order', async () => { render(); diff --git a/packages/ra-ui-materialui/src/list/datatable/DataTable.stories.tsx b/packages/ra-ui-materialui/src/list/datatable/DataTable.stories.tsx index a3e4c612bbc..a29b24d00b4 100644 --- a/packages/ra-ui-materialui/src/list/datatable/DataTable.stories.tsx +++ b/packages/ra-ui-materialui/src/list/datatable/DataTable.stories.tsx @@ -57,43 +57,43 @@ const data = { { id: 1, title: 'War and Peace', - author: 'Leo Tolstoy', + author: { name: 'Leo Tolstoy' }, year: 1869, }, { id: 2, title: 'Pride and Prejudice', - author: 'Jane Austen', + author: { name: 'Jane Austen' }, year: 1813, }, { id: 3, title: 'The Picture of Dorian Gray', - author: 'Oscar Wilde', + author: { name: 'Oscar Wilde' }, year: 1890, }, { id: 4, title: 'Le Petit Prince', - author: 'Antoine de Saint-Exupéry', + author: { name: 'Antoine de Saint-Exupéry' }, year: 1943, }, { id: 5, title: 'The Alchemist', - author: 'Paulo Coelho', + author: { name: 'Paulo Coelho' }, year: 1988, }, { id: 6, title: 'Madame Bovary', - author: 'Gustave Flaubert', + author: { name: 'Gustave Flaubert' }, year: 1857, }, { id: 7, title: 'The Lord of the Rings', - author: 'J. R. R. Tolkien', + author: { name: 'J. R. R. Tolkien' }, year: 1954, }, ], @@ -137,7 +137,7 @@ export const Basic = () => ( - + @@ -154,7 +154,7 @@ export const Columns = () => ( render={record => record.title.toUpperCase()} /> ( - +

Custom

}> - + @@ -204,7 +204,7 @@ export const Hover = () => ( - + @@ -217,14 +217,14 @@ export const Size = () => ( - +

Medium

- + @@ -242,7 +242,7 @@ export const SX = () => ( > - + @@ -260,7 +260,7 @@ export const RowSx = () => ( > - + @@ -281,7 +281,7 @@ export const StyledComponent = () => ( - + @@ -300,7 +300,7 @@ export const ColumnStyles = () => ( > - +

Cells only

@@ -313,7 +313,7 @@ export const ColumnStyles = () => ( > - +

Hidden column on small screens

@@ -327,7 +327,7 @@ export const ColumnStyles = () => ( > - + @@ -394,7 +394,7 @@ export const ErrorInFetch = () => ( - + @@ -407,7 +407,7 @@ export const RowClickFalse = () => ( - + @@ -417,7 +417,7 @@ const ExpandPanel = () => { const book = useRecordContext(); return ( - {book?.title}, by {book?.author} ({book?.year}) + {book?.title}, by {book?.author.name} ({book?.year}) ); }; @@ -427,7 +427,7 @@ export const Expand = () => ( }> - + @@ -438,7 +438,7 @@ export const ExpandSingle = () => ( } expandSingle> - + @@ -452,14 +452,14 @@ export const IsRowExpandable = () => ( - + } > - + @@ -479,28 +479,28 @@ export const BulkActionButtons = () => ( - +

Disabled

- +

Custom

}> - +

Unselectable Rows

record.id % 2 === 0}> - + @@ -520,7 +520,7 @@ export const SelectAllButton = ({ - + @@ -537,7 +537,7 @@ export const SelectAllButton = ({ > - + @@ -558,7 +558,7 @@ export const SelectAllButton = ({ > - + @@ -572,7 +572,7 @@ export const IsRowSelectable = () => ( Boolean(record.id % 2)}> - + @@ -608,7 +608,7 @@ export const Body = () => ( - + @@ -639,7 +639,7 @@ export const Head = () => ( - + @@ -767,7 +767,7 @@ export const FullApp = ({ > - + @@ -861,7 +861,7 @@ export const AccessControl = ({ - + @@ -885,3 +885,14 @@ AccessControl.argTypes = { control: { type: 'select' }, }, }; + +export const NonPrimitiveData = () => ( + defaultMessages, 'en')}> + + + + + + + +); diff --git a/packages/ra-ui-materialui/src/list/datatable/DataTableCell.tsx b/packages/ra-ui-materialui/src/list/datatable/DataTableCell.tsx index 1dab0aa0448..106effda83c 100644 --- a/packages/ra-ui-materialui/src/list/datatable/DataTableCell.tsx +++ b/packages/ra-ui-materialui/src/list/datatable/DataTableCell.tsx @@ -49,6 +49,8 @@ export const DataTableCell = React.memo( ...(cellSx && record ? cellSx(record) : {}), ...sx, } as SxProps; + + const fieldValue = get(record, source!); return ( ); }