From f988cb51458f056bd535d609a3704621b5a752b3 Mon Sep 17 00:00:00 2001 From: Lorefnon Date: Fri, 24 Nov 2023 08:11:55 +0530 Subject: [PATCH] Make Cell & HeaderCell generic (#474) * Update core components to pass around generic type params * Update example * Update tests and ts example * Perform a preliminary flattening of children so that fragments are properly handled * Prevent unnecessary re-flattening * Update docs and add test for failing typecheck --- README.md | 59 ++ docs/examples/Virtualized.md | 99 +- package.json | 1 + pnpm-lock.yaml | 9 + src/Cell.tsx | 315 +++--- src/Column.tsx | 11 +- src/HeaderCell.tsx | 249 ++--- src/Table.tsx | 1679 ++++++++++++++++---------------- src/utils/children.ts | 19 + src/utils/getColumnProps.ts | 7 +- src/utils/getTotalByColumns.ts | 10 +- src/utils/useCellDescriptor.ts | 6 +- test/Table.test.tsx | 51 + test/TableSpec.js | 20 + 14 files changed, 1389 insertions(+), 1146 deletions(-) create mode 100644 src/utils/children.ts diff --git a/README.md b/README.md index 85d08f2..0b9250b 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ const App = () => ( | autoHeight | boolean | The height of the table will be automatically expanded according to the number of data rows, and no vertical scroll bar will appear | | bordered | boolean | Show border | | cellBordered | boolean | Show cell border | +| children | (components: { Cell, HeaderCell, ColumnGroup }) => React.ReactNode | Render props that receives parameterized Cell, HeaderCell, ColumnGroup components - making typescript usage more convenient | | data \* | object[] | Table data | | defaultExpandAllRows | boolean | Expand all nodes By default | | defaultExpandedRowKeys | string[] | Specify the default expanded row by `rowkey` | @@ -238,3 +239,61 @@ const NameCell = ({ rowData, ...props }) => ( [coverage]: https://coveralls.io/github/rsuite/rsuite-table [actions-svg]: https://github.com/rsuite/rsuite-table/workflows/Node.js%20CI/badge.svg?branch=main [actions-home]: https://github.com/rsuite/rsuite-table/actions?query=branch%3Amain+workflow%3A%22Node.js+CI%22 + +### Type safety + +We can pass generic type parameters to Table, Cell etc. for better type-safety when using typescript. + +Passing a render prop to Table is recommended when using TS, as this will ensure that +the right generic type parameter is automatically propagated to the Cell component. + +```ts +const products: Product[] = [{ name: "Pineapple" }]; + + ref={table} data={products}> + {({ Column, HeaderCell, Cell }) => ( + <> + + Name + {/* No need for passing explicit type parameter to Cell */} + {row => row.name} + + + )} +; +``` + +In fact, the type parameter from table can be inferred from the data passed to it, so the type parameter to Table can also be skipped. + +```ts +const products: Product[] = [{ name: "Pineapple" }]; + + + {({ Column, HeaderCell, Cell }) => ( + <> + + Name + {row => row.name} + + + )} +
; +``` + +When writing reusable components, it is recommended to make your components generic as well. For example: + +```ts +interface ImageCellProps> { + rowData: TRow, + dataKey: TKey, + // ... any other props +} + +const ImageCell = >( + { rowData, dataKey, ...rest }: ImageCellProps +) => ( + {...rest}> + + +); +``` diff --git a/docs/examples/Virtualized.md b/docs/examples/Virtualized.md index 87e339a..ed6c4f1 100644 --- a/docs/examples/Virtualized.md +++ b/docs/examples/Virtualized.md @@ -38,52 +38,59 @@ const LargeListsTable = () => { console.log(data); }} > - - Id - - - - - Avartar - - - - - First Name - - - - - Last Name - - - - - City - - - - - Street - - - - - Company - - - - phone - - - - amount - - - - age - - + {({ Column, HeaderCell, Cell }) => ( + <> + + Id + + + + + Avartar + + + + + First Name + + + + + Last Name + + + + + City + + + + + Street + + + + + Company + + + + + phone + + + + + amount + + + + + age + + + + )}