该技能围绕 @tanstack/octane-table 的 createTableHook 展开,用于构建可复用的 Octane 表格基础设施。它建立在 @tanstack/table-core 的 core、getting-started 与 table-state 之上。文档建议:当需要复用重复约定时使用 app hook;一次性的表格仍使用 useTable。
用途
通过 createTableHook 在模块作用域创建工厂,集中管理表格特性、行 ID 获取逻辑、类型化上下文与注册组件,从而在多个表格之间复用统一约定。工厂返回的包装器具有稳定标识,能够读取最新的表格 facade,而不会重新挂载其子子树。
主要能力
- 工厂创建:从 @tanstack/octane-table 导入 createTableHook、rowSelectionFeature、tableFeatures,导出 createAppColumnHelper、useAppTable、useTableContext。
- 类型化列助手:使用 createAppColumnHelper<Person>() 创建绑定工厂的列助手,并通过 helper.columns([helper.accessor('name', { header: 'Name' })]) 定义列。
- 类型化上下文消费:在包装器下使用 useTableContext() 读取表格状态,例如行数。
- 包装器渲染:使用 JSX 渲染 AppTable、AppCell、AppHeader、AppFooter 及注册组件;包装器建立上下文与独立的 Octane 作用域。
- 静态与函数子节点:AppTable 接受静态子节点而无需选择器;当选择器提供值时使用函数子节点,例如 selector={(state) => state.rowSelection}。
- 嵌套表格隔离:默认上下文为模块作用域且对 HMR 稳定,兄弟表格由各自的 provider 隔离;嵌套工厂可能将消费者解析到内层 provider,此时可用 createTableHookContexts 为不同的嵌套设置创建全新上下文。
使用方式
- 在模块作用域创建工厂:
export const { createAppColumnHelper, useAppTable, useTableContext } = createTableHook({ features: tableFeatures({ rowSelectionFeature }), getRowId: (row: { id: string }) => row.id, })
- 使用工厂绑定的列助手定义列:
type Person = { id: string; name: string } const helper = createAppColumnHelper<Person>() const columns = helper.columns([helper.accessor('name', { header: 'Name' })])
- 在包装器下消费类型化上下文:
function RowCount() @{ const table = useTableContext() <output>{String(table.getRowModel().rows.length)}</output> }
function Grid() @{ const table = useAppTable({ data, columns }) <table.AppTable><RowCount /></table.AppTable> }
- 需要选择器值时使用函数子节点:
<table.AppTable selector={(state) => state.rowSelection}> {(rowSelection) => <output>{String(Object.keys(rowSelection).length)}</output>} </table.AppTable>
- 隔离真正嵌套的表格设置:
const features = tableFeatures({ rowSelectionFeature }) const { tableContext, cellContext, headerContext } = createTableHookContexts<typeof features>()
export const app = createTableHook({ features, tableContext, cellContext, headerContext, })
文档建议优先使用 createTableHook 返回的 hooks,因为其类型包含注册组件映射。
适用场景
- 多个表格共享重复策略、注册渲染器或类型化上下文时。
- 需要稳定包装器标识、避免子子树重新挂载时。
- 需要为不同的嵌套表格设置创建独立上下文时。
限制与常见错误
- 不要为单个表格做抽象:错误做法是 const app = createTableHook({ features: tableFeatures({}) }),正确做法是 const table = useTable({ features, columns, data })。工厂的价值在于集中重复策略、注册渲染器或类型化上下文,而不仅仅是另一个构造器名称。
- 不要在匹配的 provider 之外读取上下文:错误做法是 function Grid() @{ <RowCount /> },正确做法是先用 useAppTable 获取 table,再用 <table.AppTable><RowCount /></table.AppTable> 包裹。工厂上下文 hooks 在缺少匹配的 AppTable、AppCell 或 AppHeader provider 时会抛出可操作的错误。
- 不要在渲染期间重建工厂:错误做法是在 Grid 内调用 createTableHook,正确做法是在模块作用域创建工厂。渲染期创建的工厂会使 hook 配置、包装器、上下文与注册组件标识不稳定。
API 发现
可检查 node_modules/@tanstack/octane-table/dist/createTableHook.d.ts、createTableHookContexts.d.ts 与 types.d.ts,以获取确切的返回名称、包装器 props、注册表与作用域上下文类型。