Skip to content

Commit 295f38d

Browse files
committed
Fix DataTable crashes when its data is not a React primitive
1 parent 74d941e commit 295f38d

File tree

3 files changed

+67
-40
lines changed

3 files changed

+67
-40
lines changed

packages/ra-ui-materialui/src/list/datatable/DataTable.spec.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ExpandSingle,
1111
IsRowExpandable,
1212
IsRowSelectable,
13+
NonPrimitiveData,
1314
} from './DataTable.stories';
1415

1516
describe('DataTable', () => {
@@ -34,6 +35,17 @@ describe('DataTable', () => {
3435
screen.getByText('Author');
3536
screen.getByText('Year');
3637
});
38+
it('should render non React primitive data without crashing', async () => {
39+
render(<NonPrimitiveData />);
40+
await waitFor(() => {
41+
expect(screen.getAllByRole('row')).toHaveLength(6);
42+
});
43+
screen.getByText('War and Peace');
44+
screen.getByText('Pride and Prejudice');
45+
screen.getByText('The Picture of Dorian Gray');
46+
screen.getByText('Le Petit Prince');
47+
screen.getByText('The Alchemist');
48+
});
3749
describe('Sorting', () => {
3850
it('should show the default sort column with the default sort order', async () => {
3951
render(<Basic />);

packages/ra-ui-materialui/src/list/datatable/DataTable.stories.tsx

Lines changed: 50 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -57,43 +57,43 @@ const data = {
5757
{
5858
id: 1,
5959
title: 'War and Peace',
60-
author: 'Leo Tolstoy',
60+
author: { name: 'Leo Tolstoy' },
6161
year: 1869,
6262
},
6363
{
6464
id: 2,
6565
title: 'Pride and Prejudice',
66-
author: 'Jane Austen',
66+
author: { name: 'Jane Austen' },
6767
year: 1813,
6868
},
6969
{
7070
id: 3,
7171
title: 'The Picture of Dorian Gray',
72-
author: 'Oscar Wilde',
72+
author: { name: 'Oscar Wilde' },
7373
year: 1890,
7474
},
7575
{
7676
id: 4,
7777
title: 'Le Petit Prince',
78-
author: 'Antoine de Saint-Exupéry',
78+
author: { name: 'Antoine de Saint-Exupéry' },
7979
year: 1943,
8080
},
8181
{
8282
id: 5,
8383
title: 'The Alchemist',
84-
author: 'Paulo Coelho',
84+
author: { name: 'Paulo Coelho' },
8585
year: 1988,
8686
},
8787
{
8888
id: 6,
8989
title: 'Madame Bovary',
90-
author: 'Gustave Flaubert',
90+
author: { name: 'Gustave Flaubert' },
9191
year: 1857,
9292
},
9393
{
9494
id: 7,
9595
title: 'The Lord of the Rings',
96-
author: 'J. R. R. Tolkien',
96+
author: { name: 'J. R. R. Tolkien' },
9797
year: 1954,
9898
},
9999
],
@@ -137,7 +137,7 @@ export const Basic = () => (
137137
<DataTable>
138138
<DataTable.Col source="id" />
139139
<DataTable.Col source="title" />
140-
<DataTable.Col source="author" />
140+
<DataTable.Col label="Author" source="author.name" />
141141
<DataTable.Col source="year" />
142142
</DataTable>
143143
</Wrapper>
@@ -154,7 +154,7 @@ export const Columns = () => (
154154
render={record => record.title.toUpperCase()}
155155
/>
156156
<DataTable.Col
157-
source="author"
157+
source="author.name"
158158
sx={{
159159
color: 'darkgray',
160160
'&.MuiTableCell-body': { fontStyle: 'italic' },
@@ -185,14 +185,14 @@ export const Empty = () => (
185185
<DataTable data={[]} total={0}>
186186
<DataTable.Col source="id" />
187187
<DataTable.Col source="title" />
188-
<DataTable.Col source="author" />
188+
<DataTable.Col source="author.name" />
189189
<DataTable.Col source="year" />
190190
</DataTable>
191191
<h1>Custom</h1>
192192
<DataTable data={[]} total={0} empty={<CustomEmpty />}>
193193
<DataTable.Col source="id" />
194194
<DataTable.Col source="title" />
195-
<DataTable.Col source="author" />
195+
<DataTable.Col source="author.name" />
196196
<DataTable.Col source="year" />
197197
</DataTable>
198198
</Box>
@@ -204,7 +204,7 @@ export const Hover = () => (
204204
<DataTable hover={false}>
205205
<DataTable.Col source="id" />
206206
<DataTable.Col source="title" />
207-
<DataTable.Col source="author" />
207+
<DataTable.Col source="author.name" />
208208
<DataTable.Col source="year" />
209209
</DataTable>
210210
</Wrapper>
@@ -217,14 +217,14 @@ export const Size = () => (
217217
<DataTable>
218218
<DataTable.Col source="id" />
219219
<DataTable.Col source="title" />
220-
<DataTable.Col source="author" />
220+
<DataTable.Col source="author.name" />
221221
<DataTable.Col source="year" />
222222
</DataTable>
223223
<h1>Medium</h1>
224224
<DataTable size="medium">
225225
<DataTable.Col source="id" />
226226
<DataTable.Col source="title" />
227-
<DataTable.Col source="author" />
227+
<DataTable.Col source="author.name" />
228228
<DataTable.Col source="year" />
229229
</DataTable>
230230
</Box>
@@ -242,7 +242,7 @@ export const SX = () => (
242242
>
243243
<DataTable.Col source="id" />
244244
<DataTable.Col source="title" />
245-
<DataTable.Col source="author" />
245+
<DataTable.Col source="author.name" />
246246
<DataTable.Col source="year" />
247247
</DataTable>
248248
</Wrapper>
@@ -260,7 +260,7 @@ export const RowSx = () => (
260260
>
261261
<DataTable.Col source="id" />
262262
<DataTable.Col source="title" />
263-
<DataTable.Col source="author" />
263+
<DataTable.Col source="author.name" />
264264
<DataTable.Col source="year" />
265265
</DataTable>
266266
</Wrapper>
@@ -281,7 +281,7 @@ export const StyledComponent = () => (
281281
<StyledDataTable>
282282
<DataTable.Col source="id" />
283283
<DataTable.Col source="title" />
284-
<DataTable.Col source="author" />
284+
<DataTable.Col source="author.name" />
285285
<DataTable.Col source="year" />
286286
</StyledDataTable>
287287
</Wrapper>
@@ -300,7 +300,7 @@ export const ColumnStyles = () => (
300300
>
301301
<DataTable.Col source="id" />
302302
<DataTable.Col source="title" />
303-
<DataTable.Col source="author" />
303+
<DataTable.Col source="author.name" />
304304
<DataTable.Col source="year" />
305305
</DataTable>
306306
<h1>Cells only</h1>
@@ -313,7 +313,7 @@ export const ColumnStyles = () => (
313313
>
314314
<DataTable.Col source="id" />
315315
<DataTable.Col source="title" />
316-
<DataTable.Col source="author" />
316+
<DataTable.Col source="author.name" />
317317
<DataTable.Col source="year" />
318318
</DataTable>
319319
<h1>Hidden column on small screens</h1>
@@ -327,7 +327,7 @@ export const ColumnStyles = () => (
327327
>
328328
<DataTable.Col source="id" />
329329
<DataTable.Col source="title" />
330-
<DataTable.Col source="author" />
330+
<DataTable.Col source="author.name" />
331331
<DataTable.Col source="year" />
332332
</DataTable>
333333
</Box>
@@ -394,7 +394,7 @@ export const ErrorInFetch = () => (
394394
<DataTable>
395395
<DataTable.Col source="id" />
396396
<DataTable.Col source="title" />
397-
<DataTable.Col source="author" />
397+
<DataTable.Col source="author.name" />
398398
<DataTable.Col source="year" />
399399
</DataTable>
400400
</ResourceContextProvider>
@@ -407,7 +407,7 @@ export const RowClickFalse = () => (
407407
<DataTable rowClick={false}>
408408
<DataTable.Col source="id" />
409409
<DataTable.Col source="title" />
410-
<DataTable.Col source="author" />
410+
<DataTable.Col source="author.name" />
411411
<DataTable.Col source="year" />
412412
</DataTable>
413413
</Wrapper>
@@ -417,7 +417,7 @@ const ExpandPanel = () => {
417417
const book = useRecordContext();
418418
return (
419419
<Box data-testid="ExpandPanel" p={2}>
420-
<i>{book?.title}</i>, by {book?.author} ({book?.year})
420+
<i>{book?.title}</i>, by {book?.author.name} ({book?.year})
421421
</Box>
422422
);
423423
};
@@ -427,7 +427,7 @@ export const Expand = () => (
427427
<DataTable expand={<ExpandPanel />}>
428428
<DataTable.Col source="id" />
429429
<DataTable.Col source="title" />
430-
<DataTable.Col source="author" />
430+
<DataTable.Col source="author.name" />
431431
<DataTable.Col source="year" />
432432
</DataTable>
433433
</Wrapper>
@@ -438,7 +438,7 @@ export const ExpandSingle = () => (
438438
<DataTable expand={<ExpandPanel />} expandSingle>
439439
<DataTable.Col source="id" />
440440
<DataTable.Col source="title" />
441-
<DataTable.Col source="author" />
441+
<DataTable.Col source="author.name" />
442442
<DataTable.Col source="year" />
443443
</DataTable>
444444
</Wrapper>
@@ -452,14 +452,14 @@ export const IsRowExpandable = () => (
452452
<SimpleShowLayout>
453453
<TextField source="id" />
454454
<TextField source="title" />
455-
<TextField source="author" />
455+
<TextField source="author.name" />
456456
<TextField source="year" />
457457
</SimpleShowLayout>
458458
}
459459
>
460460
<DataTable.Col source="id" />
461461
<DataTable.Col source="title" />
462-
<DataTable.Col source="author" />
462+
<DataTable.Col source="author.name" />
463463
<DataTable.Col source="year" />
464464
</DataTable>
465465
</Wrapper>
@@ -479,28 +479,28 @@ export const BulkActionButtons = () => (
479479
<DataTable>
480480
<DataTable.Col source="id" />
481481
<DataTable.Col source="title" />
482-
<DataTable.Col source="author" />
482+
<DataTable.Col source="author.name" />
483483
<DataTable.Col source="year" />
484484
</DataTable>
485485
<h1>Disabled</h1>
486486
<DataTable bulkActionButtons={false}>
487487
<DataTable.Col source="id" />
488488
<DataTable.Col source="title" />
489-
<DataTable.Col source="author" />
489+
<DataTable.Col source="author.name" />
490490
<DataTable.Col source="year" />
491491
</DataTable>
492492
<h1>Custom</h1>
493493
<DataTable bulkActionButtons={<CustomBulkActionButtons />}>
494494
<DataTable.Col source="id" />
495495
<DataTable.Col source="title" />
496-
<DataTable.Col source="author" />
496+
<DataTable.Col source="author.name" />
497497
<DataTable.Col source="year" />
498498
</DataTable>
499499
<h1>Unselectable Rows</h1>
500500
<DataTable isRowSelectable={record => record.id % 2 === 0}>
501501
<DataTable.Col source="id" />
502502
<DataTable.Col source="title" />
503-
<DataTable.Col source="author" />
503+
<DataTable.Col source="author.name" />
504504
<DataTable.Col source="year" />
505505
</DataTable>
506506
</Box>
@@ -520,7 +520,7 @@ export const SelectAllButton = ({
520520
<DataTable>
521521
<DataTable.Col source="id" />
522522
<DataTable.Col source="title" />
523-
<DataTable.Col source="author" />
523+
<DataTable.Col source="author.name" />
524524
<DataTable.Col source="year" />
525525
</DataTable>
526526
</>
@@ -537,7 +537,7 @@ export const SelectAllButton = ({
537537
>
538538
<DataTable.Col source="id" />
539539
<DataTable.Col source="title" />
540-
<DataTable.Col source="author" />
540+
<DataTable.Col source="author.name" />
541541
<DataTable.Col source="year" />
542542
</DataTable>
543543
</>
@@ -558,7 +558,7 @@ export const SelectAllButton = ({
558558
>
559559
<DataTable.Col source="id" />
560560
<DataTable.Col source="title" />
561-
<DataTable.Col source="author" />
561+
<DataTable.Col source="author.name" />
562562
<DataTable.Col source="year" />
563563
</DataTable>
564564
</>
@@ -572,7 +572,7 @@ export const IsRowSelectable = () => (
572572
<DataTable isRowSelectable={record => Boolean(record.id % 2)}>
573573
<DataTable.Col source="id" />
574574
<DataTable.Col source="title" />
575-
<DataTable.Col source="author" />
575+
<DataTable.Col source="author.name" />
576576
<DataTable.Col source="year" />
577577
</DataTable>
578578
</Wrapper>
@@ -608,7 +608,7 @@ export const Body = () => (
608608
<DataTable body={MyDataTableBody}>
609609
<DataTable.Col source="id" />
610610
<DataTable.Col source="title" />
611-
<DataTable.Col source="author" />
611+
<DataTable.Col source="author.name" />
612612
<DataTable.Col source="year" />
613613
</DataTable>
614614
</Wrapper>
@@ -639,7 +639,7 @@ export const Head = () => (
639639
<DataTable head={MyDataTableHead}>
640640
<DataTable.Col source="id" />
641641
<DataTable.Col source="title" />
642-
<DataTable.Col source="author" />
642+
<DataTable.Col source="author.name" />
643643
<DataTable.Col source="year" />
644644
</DataTable>
645645
</Wrapper>
@@ -767,7 +767,7 @@ export const FullApp = ({
767767
>
768768
<DataTable.Col source="id" />
769769
<DataTable.Col source="title" />
770-
<DataTable.Col source="author" />
770+
<DataTable.Col source="author.name" />
771771
<DataTable.Col source="year" />
772772
</DataTable>
773773
</List>
@@ -861,7 +861,7 @@ export const AccessControl = ({
861861
<DataTable key={allowedAction}>
862862
<DataTable.Col source="id" />
863863
<DataTable.Col source="title" />
864-
<DataTable.Col source="author" />
864+
<DataTable.Col source="author.name" />
865865
<DataTable.Col source="year" />
866866
</DataTable>
867867
</List>
@@ -885,3 +885,14 @@ AccessControl.argTypes = {
885885
control: { type: 'select' },
886886
},
887887
};
888+
889+
export const NonPrimitiveData = () => (
890+
<Wrapper i18nProvider={polyglotI18nProvider(() => defaultMessages, 'en')}>
891+
<DataTable>
892+
<DataTable.Col source="id" />
893+
<DataTable.Col source="title" />
894+
<DataTable.Col source="author" />
895+
<DataTable.Col source="year" />
896+
</DataTable>
897+
</Wrapper>
898+
);

packages/ra-ui-materialui/src/list/datatable/DataTableCell.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export const DataTableCell = React.memo(
4949
...(cellSx && record ? cellSx(record) : {}),
5050
...sx,
5151
} as SxProps;
52+
53+
const fieldValue = get(record, source!);
5254
return (
5355
<TableCellStyled
5456
ref={ref}
@@ -65,7 +67,9 @@ export const DataTableCell = React.memo(
6567
? record && render(record)
6668
: field
6769
? React.createElement(field, { source })
68-
: get(record, source!))}
70+
: fieldValue != null
71+
? fieldValue.toString()
72+
: null)}
6973
</TableCellStyled>
7074
);
7175
}

0 commit comments

Comments
 (0)