tanstack-table

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Documentation

文档说明

Use
context7
for the latest documentation. Use
deepwiki
to ask questions about the library's implementation.
使用
context7
获取最新文档。使用
deepwiki
咨询该库实现相关的问题。

TanStack Table Patterns

TanStack Table 模式

This skill covers TanStack Table library patterns with the
meta
field for passing behavior to cells.
本技能介绍如何在TanStack Table库中使用
meta
字段向单元格传递行为的相关模式。

Core Pattern: Hoisted Columns with Meta

核心模式:通过Meta实现列定义提升

typescript
// 1. Extend TableMeta for type safety
declare module '@tanstack/react-table' {
	interface TableMeta<TData extends RowData> {
		onEdit?: (id: string) => void;
		onDelete?: (id: string) => void;
	}
}

// 2. Hoist column definitions outside component
const columnHelper = createColumnHelper<Job>();

const columns = [
	columnHelper.accessor('name', {
		header: 'Name',
		cell: info => info.getValue(),
	}),
	columnHelper.display({
		id: 'actions',
		cell: ({ row, table }) => (
			<Button onClick={() => table.options.meta?.onEdit?.(row.original.id)}>Edit</Button>
		),
	}),
];

// 3. Pass callbacks via meta
function DataTable({ data, onEdit, onDelete }: Props) {
	const table = useReactTable({
		data,
		columns,
		getCoreRowModel: getCoreRowModel(),
		meta: { onEdit, onDelete },
	});

	return <Table>...</Table>;
}
typescript
// 1. 扩展TableMeta以实现类型安全
declare module '@tanstack/react-table' {
	interface TableMeta<TData extends RowData> {
		onEdit?: (id: string) => void;
		onDelete?: (id: string) => void;
	}
}

// 2. 将列定义提升至组件外部
const columnHelper = createColumnHelper<Job>();

const columns = [
	columnHelper.accessor('name', {
		header: 'Name',
		cell: info => info.getValue(),
	}),
	columnHelper.display({
		id: 'actions',
		cell: ({ row, table }) => (
			<Button onClick={() => table.options.meta?.onEdit?.(row.original.id)}>Edit</Button>
		),
	}),
];

// 3. 通过meta传递回调函数
function DataTable({ data, onEdit, onDelete }: Props) {
	const table = useReactTable({
		data,
		columns,
		getCoreRowModel: getCoreRowModel(),
		meta: { onEdit, onDelete },
	});

	return <Table>...</Table>;
}

Why Meta Over Closures?

为什么选择Meta而非闭包?

Closures in column definitions cause re-renders:
typescript
// Bad - new column array every render
const columns = useMemo(() => [
  {
    cell: ({ row }) => (
      <Button onClick={() => onEdit(row.original.id)}>Edit</Button>
    ),
  },
], [onEdit]); // Invalidates when onEdit changes

// Good - stable columns, dynamic meta
const columns = [...]; // Hoisted, never changes

const table = useReactTable({
  meta: { onEdit }, // Only meta changes
});
列定义中的闭包会导致重渲染:
typescript
// 不推荐 - 每次渲染都会创建新的列数组
const columns = useMemo(() => [
  {
    cell: ({ row }) => (
      <Button onClick={() => onEdit(row.original.id)}>Edit</Button>
    ),
  },
], [onEdit]); // 当onEdit变化时会失效

// 推荐 - 稳定的列定义,动态meta
const columns = [...]; // 提升至外部,永不改变

const table = useReactTable({
  meta: { onEdit }, // 仅meta会变化
});

References

参考资料

  • For column definition patterns, see column-definitions.md
  • For meta field type safety, see meta-field.md
  • 关于列定义模式,请查看column-definitions.md
  • 关于meta字段类型安全,请查看meta-field.md