框架
版本
企业版

迁移到 V8 指南

迁移到 V8

TanStack Table V8 是 React Table v7 的一次彻底重写,从头开始用 TypeScript 构建。您的标记和 CSS 的整体结构/组织在很大程度上将保持不变,但许多 API 已重命名或替换。

重要变更

  • 完全重写为 TypeScript,并在基础包中包含类型
  • 移除插件系统,以支持更多的控制反转
  • API 大幅扩展和改进(以及诸如固定列等新功能)
  • 更好的受控状态管理
  • 对服务端操作更好的支持
  • 完整(但可选)的数据管道控制
  • 核心框架独立,并提供 React、Solid、Svelte、Vue 的适配器,未来可能支持更多
  • 新的开发者工具

安装新版本

新版本的 TanStack Table 发布在 @tanstack 作用域下。使用您喜欢的包管理器安装新包

bash
npm uninstall react-table @types/react-table
npm install @tanstack/react-table
npm uninstall react-table @types/react-table
npm install @tanstack/react-table
tsx
- import { useTable } from 'react-table' // [!code --]
+ import { useReactTable } from '@tanstack/react-table' // [!code ++]
- import { useTable } from 'react-table' // [!code --]
+ import { useReactTable } from '@tanstack/react-table' // [!code ++]

类型现已包含在基础包中,因此您可以移除 @types/react-table 包。

如果您愿意,可以保留已安装的旧 react-table 包,以便逐步迁移代码。您应该能够将这两个包并排用于不同的表格,而不会出现任何问题。

更新表格选项

  • useTable 重命名为 useReactTable
  • 已移除旧的钩子和插件系统,但已用可摇树优化的行模型导入替换了每个功能。
tsx
- import { useTable, usePagination, useSortBy } from 'react-table'; // [!code --]
+ import { // [!code ++]
+   useReactTable, // [!code ++]
+   getCoreRowModel, // [!code ++]
+   getPaginationRowModel, // [!code ++]
+   getSortedRowModel // [!code ++]
+ } from '@tanstack/react-table'; // [!code ++]

// ...

-   const tableInstance = useTable( // [!code --]
-     { columns,  data }, // [!code --]
-     useSortBy, // [!code --]
-     usePagination, //order of hooks used to matter // [!code --]
-     // etc. // [!code --]
-   ); // [!code --]
+   const tableInstance = useReactTable({ // [!code ++]
+     columns, // [!code ++]
+     data, // [!code ++]
+     getCoreRowModel: getCoreRowModel(), // [!code ++]
+     getPaginationRowModel: getPaginationRowModel(), // [!code ++]
+     getSortedRowModel: getSortedRowModel(), //order doesn't matter anymore! // [!code ++]
+     // etc. // [!code ++]
+   }); // [!code ++]
- import { useTable, usePagination, useSortBy } from 'react-table'; // [!code --]
+ import { // [!code ++]
+   useReactTable, // [!code ++]
+   getCoreRowModel, // [!code ++]
+   getPaginationRowModel, // [!code ++]
+   getSortedRowModel // [!code ++]
+ } from '@tanstack/react-table'; // [!code ++]

// ...

-   const tableInstance = useTable( // [!code --]
-     { columns,  data }, // [!code --]
-     useSortBy, // [!code --]
-     usePagination, //order of hooks used to matter // [!code --]
-     // etc. // [!code --]
-   ); // [!code --]
+   const tableInstance = useReactTable({ // [!code ++]
+     columns, // [!code ++]
+     data, // [!code ++]
+     getCoreRowModel: getCoreRowModel(), // [!code ++]
+     getPaginationRowModel: getPaginationRowModel(), // [!code ++]
+     getSortedRowModel: getSortedRowModel(), //order doesn't matter anymore! // [!code ++]
+     // etc. // [!code ++]
+   }); // [!code ++]
  • 所有 disable* 表格选项均已重命名为 enable* 表格选项。(例如,disableSortBy 现在是 enableSortingdisableGroupBy 现在是 enableGrouping,依此类推)
  • ...

更新列定义

  • accessor 已重命名为 accessorKeyaccessorFn(取决于您使用的是字符串还是函数)
  • width、minWidth、maxWidth 已重命名为 size、minSize、maxSize
  • 可选地,您可以使用新的 createColumnHelper 函数围绕每个列定义,以获得更好的 TypeScript 提示。(如果您愿意,仍然可以使用列定义数组。)
    • 第一个参数是 accessor 函数或 accessor 字符串。
    • 第二个参数是列选项对象。
tsx
const columns = [
-  { // [!code --]
-    accessor: 'firstName', // [!code --]
-    Header: 'First Name', // [!code --]
-  }, // [!code --]
-  { // [!code --]
-    accessor: row => row.lastName, // [!code --]
-    Header: () => <span>Last Name</span>, // [!code --]
-  }, // [!code --]

// Best TypeScript experience, especially when using `cell.getValue()` later on
+  columnHelper.accessor('firstName', { //accessorKey // [!code ++]
+    header: 'First Name', // [!code ++]
+  }), // [!code ++]
+  columnHelper.accessor(row => row.lastName, { //accessorFn // [!code ++]
+    header: () => <span>Last Name</span>, // [!code ++]
+  }), // [!code ++]

// OR (if you prefer)
+ { // [!code ++]
+   accessorKey: 'firstName', // [!code ++]
+   header: 'First Name', // [!code ++]
+ }, // [!code ++]
+ { // [!code ++]
+   accessorFn: row => row.lastName, // [!code ++]
+   header: () => <span>Last Name</span>, // [!code ++]
+ }, // [!code ++]
]
const columns = [
-  { // [!code --]
-    accessor: 'firstName', // [!code --]
-    Header: 'First Name', // [!code --]
-  }, // [!code --]
-  { // [!code --]
-    accessor: row => row.lastName, // [!code --]
-    Header: () => <span>Last Name</span>, // [!code --]
-  }, // [!code --]

// Best TypeScript experience, especially when using `cell.getValue()` later on
+  columnHelper.accessor('firstName', { //accessorKey // [!code ++]
+    header: 'First Name', // [!code ++]
+  }), // [!code ++]
+  columnHelper.accessor(row => row.lastName, { //accessorFn // [!code ++]
+    header: () => <span>Last Name</span>, // [!code ++]
+  }), // [!code ++]

// OR (if you prefer)
+ { // [!code ++]
+   accessorKey: 'firstName', // [!code ++]
+   header: 'First Name', // [!code ++]
+ }, // [!code ++]
+ { // [!code ++]
+   accessorFn: row => row.lastName, // [!code ++]
+   header: () => <span>Last Name</span>, // [!code ++]
+ }, // [!code ++]
]

注意:如果在一个组件内定义列,您仍然应该尝试为列定义提供稳定的身份。这将有助于提高性能并防止不必要的重新渲染。将列定义存储在 useMemouseState 钩子中。

  • 列选项名称更改

    • Header 已重命名为 header
    • Cell 已重命名为 cell(单元格渲染函数也有所更改。见下文)
    • Footer 已重命名为 footer
    • 所有 disable* 列选项均已重命名为 enable* 列选项。(例如,disableSortBy 现在是 enableSortingdisableGroupBy 现在是 enableGrouping,依此类推)
    • sortType sortingFn
    • ...
  • 自定义单元格渲染器变更

    • value 已重命名为 getValue(在整个升级过程中,不再直接提供 value,而是提供一个名为 getValue 的函数来评估 value。此更改旨在通过仅在调用 getValue() 时评估 value 并缓存它来提高性能。)
    • cell: { isGrouped, isPlaceholder, isAggregated } 现在是 cell: { getIsGrouped, getIsPlaceholder, getIsAggregated }
    • column:基础级别的 props 现在是 RT 特定的。您在定义它时添加到该对象的值现在位于 columnDef 的更深一层。
    • table:传递给 useTable 钩子的 props 现在出现在 options 下。

迁移表格标记

  • 使用 flexRender() 替代 cell.render('Cell')column.render('Header') 等。
  • getHeaderPropsgetFooterPropsgetCellPropsgetRowProps 等均已弃用
    • TanStack Table 不再提供任何默认的 style 或可访问性属性,例如 role。这些对于您正确实现仍然很重要,但为了支持框架的独立性,必须将其移除。
    • 您需要手动定义 onClick 处理程序,但提供了新的 get*Handler 助手来简化此过程。
    • 您需要手动定义 key 属性
    • 如果您使用需要它的功能(分组标题、聚合等),则需要手动定义 colSpan 属性。
tsx
- <th {...header.getHeaderProps()}>{cell.render('Header')}</th> // [!code --]
+ <th colSpan={header.colSpan} key={column.id}> // [!code ++]
+   {flexRender( // [!code ++]
+     header.column.columnDef.header, // [!code ++]
+     header.getContext() // [!code ++]
+   )} // [!code ++]
+ </th> // [!code ++]
- <th {...header.getHeaderProps()}>{cell.render('Header')}</th> // [!code --]
+ <th colSpan={header.colSpan} key={column.id}> // [!code ++]
+   {flexRender( // [!code ++]
+     header.column.columnDef.header, // [!code ++]
+     header.getContext() // [!code ++]
+   )} // [!code ++]
+ </th> // [!code ++]
tsx
- <td {...cell.getCellProps()}>{cell.render('Cell')}</td> // [!code --]
+ <td key={cell.id}> // [!code ++]
+   {flexRender( // [!code ++]
+     cell.column.columnDef.cell, // [!code ++]
+     cell.getContext() // [!code ++]
+   )} // [!code ++]
+ </td> // [!code ++]
- <td {...cell.getCellProps()}>{cell.render('Cell')}</td> // [!code --]
+ <td key={cell.id}> // [!code ++]
+   {flexRender( // [!code ++]
+     cell.column.columnDef.cell, // [!code ++]
+     cell.getContext() // [!code ++]
+   )} // [!code ++]
+ </td> // [!code ++]
tsx
// in column definitions in this case
- Header: ({ getToggleAllRowsSelectedProps }) => ( // [!code --]
-   <input type="checkbox" {...getToggleAllRowsSelectedProps()} /> // [!code --]
- ), // [!code --]
- Cell: ({ row }) => ( // [!code --]
-   <input type="checkbox" {...row.getToggleRowSelectedProps()} /> // [!code --]
- ), // [!code --]
+ header: ({ table }) => ( // [!code ++]
+   <Checkbox // [!code ++]
+     checked={table.getIsAllRowsSelected()} // [!code ++]
+     indeterminate={table.getIsSomeRowsSelected()} // [!code ++]
+     onChange={table.getToggleAllRowsSelectedHandler()} // [!code ++]
+   /> // [!code ++]
+ ), // [!code ++]
+ cell: ({ row }) => ( // [!code ++]
+   <Checkbox // [!code ++]
+     checked={row.getIsSelected()} // [!code ++]
+     disabled={!row.getCanSelect()} // [!code ++]
+     indeterminate={row.getIsSomeSelected()} // [!code ++]
+     onChange={row.getToggleSelectedHandler()} // [!code ++]
+   /> // [!code ++]
+ ), // [!code ++]
// in column definitions in this case
- Header: ({ getToggleAllRowsSelectedProps }) => ( // [!code --]
-   <input type="checkbox" {...getToggleAllRowsSelectedProps()} /> // [!code --]
- ), // [!code --]
- Cell: ({ row }) => ( // [!code --]
-   <input type="checkbox" {...row.getToggleRowSelectedProps()} /> // [!code --]
- ), // [!code --]
+ header: ({ table }) => ( // [!code ++]
+   <Checkbox // [!code ++]
+     checked={table.getIsAllRowsSelected()} // [!code ++]
+     indeterminate={table.getIsSomeRowsSelected()} // [!code ++]
+     onChange={table.getToggleAllRowsSelectedHandler()} // [!code ++]
+   /> // [!code ++]
+ ), // [!code ++]
+ cell: ({ row }) => ( // [!code ++]
+   <Checkbox // [!code ++]
+     checked={row.getIsSelected()} // [!code ++]
+     disabled={!row.getCanSelect()} // [!code ++]
+     indeterminate={row.getIsSomeSelected()} // [!code ++]
+     onChange={row.getToggleSelectedHandler()} // [!code ++]
+   /> // [!code ++]
+ ), // [!code ++]

其他变更

  • 自定义 filterTypes(现在称为 filterFns)具有新的函数签名,因为它只返回一个布尔值,指示该行是否应被包含。
tsx
- (rows: Row[], id: string, filterValue: any) => Row[] // [!code --]
+ (row: Row, id: string, filterValue: any) => boolean // [!code ++]
- (rows: Row[], id: string, filterValue: any) => Row[] // [!code --]
+ (row: Row, id: string, filterValue: any) => boolean // [!code ++]
  • ...

本指南仍在进行中。如果您有时间,请考虑为此做出贡献!

我们的合作伙伴
Code Rabbit
AG Grid
订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

无垃圾邮件。您可以随时取消订阅。

订阅 Bytes

您的每周 JavaScript 资讯。每周一免费发送给超过 10 万开发者。

Bytes

无垃圾邮件。您可以随时取消订阅。