tanstack-table
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTanStack Table
TanStack Table
Version: @tanstack/react-table@latest
Requires: React 16.8+, TypeScript recommended
版本: @tanstack/react-table@latest
要求: React 16.8+,推荐使用TypeScript
Quick Setup
快速开始
bash
npm install @tanstack/react-tabletsx
import {
useReactTable,
getCoreRowModel,
flexRender,
createColumnHelper,
} from '@tanstack/react-table'
type User = {
name: string
age: number
status: string
}
const columnHelper = createColumnHelper<User>()
const columns = [
columnHelper.accessor('name', { header: 'Name' }),
columnHelper.accessor('age', { header: 'Age' }),
columnHelper.accessor('status', { header: 'Status' }),
columnHelper.display({
id: 'actions',
cell: (props) => <button onClick={() => edit(props.row.original)}>Edit</button>,
}),
]
function App() {
const [data] = useState<User[]>([]) // must be stable reference
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
{flexRender(header.column.columnDef.header, header.getContext())}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
)
}bash
npm install @tanstack/react-tabletsx
import {
useReactTable,
getCoreRowModel,
flexRender,
createColumnHelper,
} from '@tanstack/react-table'
type User = {
name: string
age: number
status: string
}
const columnHelper = createColumnHelper<User>()
const columns = [
columnHelper.accessor('name', { header: 'Name' }),
columnHelper.accessor('age', { header: 'Age' }),
columnHelper.accessor('status', { header: 'Status' }),
columnHelper.display({
id: 'actions',
cell: (props) => <button onClick={() => edit(props.row.original)}>Edit</button>,
}),
]
function App() {
const [data] = useState<User[]>([]) // must be stable reference
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<th key={header.id}>
{flexRender(header.column.columnDef.header, header.getContext())}
</th>
))}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (
<tr key={row.id}>
{row.getVisibleCells().map((cell) => (
<td key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
</table>
)
}Row Models (Import Only What You Need)
行模型(仅导入所需模块)
TanStack Table is modular. Only import the row models you actually use:
tsx
import {
getCoreRowModel, // required
getSortedRowModel, // client-side sorting
getFilteredRowModel, // client-side filtering
getPaginationRowModel,// client-side pagination
getExpandedRowModel, // expanding/sub-rows
getGroupedRowModel, // grouping + aggregation
getFacetedRowModel, // faceted values
getFacetedUniqueValues,
getFacetedMinMaxValues,
} from '@tanstack/react-table'Pipeline order: Core -> Filtered -> Grouped -> Sorted -> Expanded -> Paginated -> Rendered
TanStack Table采用模块化设计。仅导入实际使用的行模型:
tsx
import {
getCoreRowModel, // required
getSortedRowModel, // client-side sorting
getFilteredRowModel, // client-side filtering
getPaginationRowModel,// client-side pagination
getExpandedRowModel, // expanding/sub-rows
getGroupedRowModel, // grouping + aggregation
getFacetedRowModel, // faceted values
getFacetedUniqueValues,
getFacetedMinMaxValues,
} from '@tanstack/react-table'执行顺序:Core -> Filtered -> Grouped -> Sorted -> Expanded -> Paginated -> Rendered
Rule Categories
规则分类
| Priority | Category | Rule File | Impact |
|---|---|---|---|
| CRITICAL | Table Setup | | Correct table creation, stable data references |
| CRITICAL | Column Definitions | | Data model, rendering, type safety |
| CRITICAL | Row Models | | Modular imports, pipeline order |
| HIGH | Sorting | | Client/server sorting, custom sort functions |
| HIGH | Column Filtering | | Per-column filters, custom filter functions |
| HIGH | Global Filtering | | Table-wide search, global filter function |
| HIGH | Pagination | | Client/server pagination, page state |
| MEDIUM | Row Selection | | Checkbox/radio selection, selection state |
| MEDIUM | Column Visibility | | Show/hide columns dynamically |
| MEDIUM | Column Sizing | | Widths, resizing, performance |
| LOW | Expanding | | Sub-rows, detail panels, hierarchical data |
| 优先级 | 分类 | 规则文件 | 影响 |
|---|---|---|---|
| CRITICAL | 表格设置 | | 正确创建表格,稳定的数据引用 |
| CRITICAL | 列定义 | | 数据模型、渲染、类型安全 |
| CRITICAL | 行模型 | | 模块化导入、执行顺序 |
| HIGH | 排序 | | 客户端/服务端排序、自定义排序函数 |
| HIGH | 列筛选 | | 列级筛选、自定义筛选函数 |
| HIGH | 全局筛选 | | 表格全局搜索、全局筛选函数 |
| HIGH | 分页 | | 客户端/服务端分页、页面状态 |
| MEDIUM | 行选择 | | 复选框/单选框选择、选择状态 |
| MEDIUM | 列可见性 | | 动态显示/隐藏列 |
| MEDIUM | 列尺寸 | | 宽度、调整尺寸、性能 |
| LOW | 展开 | | 子行、详情面板、层级数据 |
Critical Rules
关键规则
Always Do
必做事项
- Stable reference — use
data,useState, or define outside component to prevent infinite re-rendersuseMemo - Use — for maximum type safety in column definitions
createColumnHelper<TData>() - Import only needed row models — don't import if you don't sort client-side
getSortedRowModel - Use — for rendering header/cell/footer templates from column defs
flexRender - Use — not
getVisibleCells(), to respect column visibilitygetAllCells() - Use — the final row model that applies all features (filtering, sorting, pagination)
getRowModel() - Control state with +
state— for sorting, filtering, pagination, selection, etc.on*Change
- 稳定的引用 — 使用
data、useState或在组件外部定义,以避免无限重渲染useMemo - 使用— 为列定义提供最大程度的类型安全
createColumnHelper<TData>() - 仅导入所需的行模型 — 如果不使用客户端排序,请勿导入
getSortedRowModel - 使用— 从列定义中渲染表头/单元格/页脚模板
flexRender - 使用— 而非
getVisibleCells(),以遵循列可见性设置getAllCells() - 使用— 最终应用所有功能(筛选、排序、分页)的行模型
getRowModel() - 通过+
state控制状态 — 用于排序、筛选、分页、选择等功能on*Change
Never Do
禁止事项
- Define inline —
datacauses infinite re-rendersuseReactTable({ data: fetchData() }) - Define inside render — columns array must be stable (define outside component or
columns)useMemo - Use for rendering — ignores column visibility; use
getAllCells()getVisibleCells() - Mix and
initialStatefor the same feature —stateoverridesstateinitialState - Use client-side row models with options — if
manual*, don't importmanualSorting: truegetSortedRowModel - Forget — without it, row IDs default to index, breaking selection state across re-fetches
getRowId
- 内联定义—
data会导致无限重渲染useReactTable({ data: fetchData() }) - 在渲染函数内定义— 列数组必须保持稳定(在组件外部定义或使用
columns)useMemo - 使用进行渲染 — 会忽略列可见性设置;请使用
getAllCells()getVisibleCells() - 为同一功能混合使用和
initialState—state会覆盖stateinitialState - 在启用选项时使用客户端行模型 — 如果设置
manual*,请勿导入manualSorting: truegetSortedRowModel - 忘记设置— 不设置的话,行ID默认使用索引,会导致重新获取数据时选择状态失效
getRowId
Key Patterns
核心模式
tsx
// Controlled sorting state
const [sorting, setSorting] = useState<SortingState>([])
const table = useReactTable({
data, columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
state: { sorting },
onSortingChange: setSorting,
})
// Header click handler
<th onClick={header.column.getToggleSortingHandler()}>
{flexRender(header.column.columnDef.header, header.getContext())}
{{ asc: ' 🔼', desc: ' 🔽' }[header.column.getIsSorted() as string] ?? ''}
</th>
// Server-side pagination
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 })
const table = useReactTable({
data, columns,
getCoreRowModel: getCoreRowModel(),
manualPagination: true,
rowCount: serverData.totalRows,
state: { pagination },
onPaginationChange: setPagination,
})
// Row selection with checkbox column
columnHelper.display({
id: 'select',
header: ({ table }) => (
<input type="checkbox" checked={table.getIsAllRowsSelected()}
onChange={table.getToggleAllRowsSelectedHandler()} />
),
cell: ({ row }) => (
<input type="checkbox" checked={row.getIsSelected()}
disabled={!row.getCanSelect()}
onChange={row.getToggleSelectedHandler()} />
),
})
// Column filtering
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
const table = useReactTable({
data, columns,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
state: { columnFilters },
onColumnFiltersChange: setColumnFilters,
})
// Filter input
<input value={column.getFilterValue() ?? ''} onChange={e => column.setFilterValue(e.target.value)} />
// Stable row IDs for selection across re-fetches
const table = useReactTable({
data, columns,
getRowId: (row) => row.uuid,
getCoreRowModel: getCoreRowModel(),
})tsx
// Controlled sorting state
const [sorting, setSorting] = useState<SortingState>([])
const table = useReactTable({
data, columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
state: { sorting },
onSortingChange: setSorting,
})
// Header click handler
<th onClick={header.column.getToggleSortingHandler()}>
{flexRender(header.column.columnDef.header, header.getContext())}
{{ asc: ' 🔼', desc: ' 🔽' }[header.column.getIsSorted() as string] ?? ''}
</th>
// Server-side pagination
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 })
const table = useReactTable({
data, columns,
getCoreRowModel: getCoreRowModel(),
manualPagination: true,
rowCount: serverData.totalRows,
state: { pagination },
onPaginationChange: setPagination,
})
// Row selection with checkbox column
columnHelper.display({
id: 'select',
header: ({ table }) => (
<input type="checkbox" checked={table.getIsAllRowsSelected()}
onChange={table.getToggleAllRowsSelectedHandler()} />
),
cell: ({ row }) => (
<input type="checkbox" checked={row.getIsSelected()}
disabled={!row.getCanSelect()}
onChange={row.getToggleSelectedHandler()} />
),
})
// Column filtering
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
const table = useReactTable({
data, columns,
getCoreRowModel: getCoreRowModel(),
getFilteredRowModel: getFilteredRowModel(),
state: { columnFilters },
onColumnFiltersChange: setColumnFilters,
})
// Filter input
<input value={column.getFilterValue() ?? ''} onChange={e => column.setFilterValue(e.target.value)} />
// Stable row IDs for selection across re-fetches
const table = useReactTable({
data, columns,
getRowId: (row) => row.uuid,
getCoreRowModel: getCoreRowModel(),
})