fix(ui)!: remove Fragment wrapper in Table to prevent id prop error
React Aria's Collection component injects an `id` prop into rendered children. When children were wrapped in Fragment, this caused "Invalid prop `id` supplied to `React.Fragment`" errors on render. BREAKING CHANGE: The `cell` and `header` properties in `ColumnConfig` now return `ReactElement` instead of `ReactNode`. Cell and header functions that return non-element values must be updated to always return a valid element. Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
---
|
||||
'@backstage/ui': minor
|
||||
---
|
||||
|
||||
**BREAKING**: The `cell` and `header` properties in `ColumnConfig` now return `ReactElement` instead of `ReactNode`.
|
||||
|
||||
This fixes an issue where React Aria's Collection component would inject an `id` prop into Fragment wrappers, causing "Invalid prop `id` supplied to `React.Fragment`" errors on render.
|
||||
|
||||
Migration:
|
||||
|
||||
```diff
|
||||
const columns: ColumnConfig<MyItem>[] = [
|
||||
{
|
||||
id: 'name',
|
||||
label: 'Name',
|
||||
- cell: (item) => item.name,
|
||||
+ cell: (item) => <CellText title={item.name} />,
|
||||
- header: () => 'Name',
|
||||
+ header: () => <Column>Name</Column>,
|
||||
},
|
||||
];
|
||||
```
|
||||
@@ -479,11 +479,11 @@ export const Column: (props: ColumnProps) => JSX_2.Element;
|
||||
// @public (undocumented)
|
||||
export interface ColumnConfig<T extends TableItem> {
|
||||
// (undocumented)
|
||||
cell: (item: T) => ReactNode;
|
||||
cell: (item: T) => ReactElement;
|
||||
// (undocumented)
|
||||
defaultWidth?: ColumnSize | null;
|
||||
// (undocumented)
|
||||
header?: () => ReactNode;
|
||||
header?: () => ReactElement;
|
||||
// (undocumented)
|
||||
id: string;
|
||||
// (undocumented)
|
||||
|
||||
@@ -29,7 +29,7 @@ import type {
|
||||
RowRenderFn,
|
||||
TablePaginationType,
|
||||
} from '../types';
|
||||
import { Fragment, useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { VisuallyHidden } from '../../VisuallyHidden';
|
||||
import { Flex } from '../../Flex';
|
||||
|
||||
@@ -158,7 +158,7 @@ export function Table<T extends TableItem>({
|
||||
<TableHeader columns={visibleColumns}>
|
||||
{column =>
|
||||
column.header ? (
|
||||
<>{column.header()}</>
|
||||
column.header()
|
||||
) : (
|
||||
<Column
|
||||
id={column.id}
|
||||
@@ -201,9 +201,7 @@ export function Table<T extends TableItem>({
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{column => (
|
||||
<Fragment key={column.id}>{column.cell(item)}</Fragment>
|
||||
)}
|
||||
{column => column.cell(item)}
|
||||
</Row>
|
||||
);
|
||||
}}
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
ColumnProps as ReactAriaColumnProps,
|
||||
TableProps as ReactAriaTableProps,
|
||||
} from 'react-aria-components';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ReactElement, ReactNode } from 'react';
|
||||
import type { SortDescriptor as ReactStatelySortDescriptor } from 'react-stately';
|
||||
import type { ColumnSize, ColumnStaticSize } from '@react-types/table';
|
||||
import type { TextColors } from '../../types';
|
||||
@@ -89,8 +89,8 @@ export type TablePaginationType = NoPagination | PagePagination;
|
||||
export interface ColumnConfig<T extends TableItem> {
|
||||
id: string;
|
||||
label: string;
|
||||
cell: (item: T) => ReactNode;
|
||||
header?: () => ReactNode;
|
||||
cell: (item: T) => ReactElement;
|
||||
header?: () => ReactElement;
|
||||
isSortable?: boolean;
|
||||
isHidden?: boolean;
|
||||
width?: ColumnSize | null;
|
||||
|
||||
Reference in New Issue
Block a user