Use TanStack Table v9 as a headless data-grid state and row-processing engine. Load for first-table architecture, stable data and columns, row numbering with getDisplayIndex, semantic rendering, framework adapter choice, or deciding what Table owns versus the renderer.
66
80%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
TanStack Table creates a table instance, state, and row models. It does not render a component, choose a component library, apply CSS, or supply interaction accessibility. Use a framework adapter in UI code; use constructTable only for framework-neutral integrations.
import {
constructTable,
createColumnHelper,
tableFeatures,
} from '@tanstack/table-core'
import { storeReactivityBindings } from '@tanstack/table-core/store-reactivity-bindings'
type Person = { id: string; name: string }
const features = tableFeatures({
coreReactivityFeature: storeReactivityBindings(),
})
const helper = createColumnHelper<typeof features, Person>()
const columns = helper.columns([helper.accessor('name', { header: 'Name' })])
const data: Person[] = [{ id: '1', name: 'Ada' }]
const table = constructTable({
features,
columns,
data,
getRowId: (row) => row.id,
})
for (const row of table.getRowModel().rows) {
console.log(row.getAllCells().map((cell) => cell.getValue()))
}const features = tableFeatures({
coreReactivityFeature: storeReactivityBindings(),
})The core row model is automatic; filtering, sorting, pagination, and other optional behavior require their feature plugins.
const data: Person[] = [{ id: '1', name: 'Ada' }]
const columns = helper.columns([helper.accessor('name', { header: 'Name' })])Define static inputs once and preserve query/store references when data has not changed.
const rowNumberColumn = helper.display({
id: 'rowNumber',
header: '#',
cell: ({ row }) => {
const displayIndex = row.getDisplayIndex()
return displayIndex === -1 ? '' : displayIndex + 1
},
})row.getDisplayIndex() follows the current filtering, grouping, sorting, and expansion order before pagination. row.index remains the row's creation-time position within its parent array.
Wrong:
document.body.append(table as unknown as Node)Correct:
const names = table
.getRowModel()
.rows.map((row) => row.getValue<string>('name'))
document.body.textContent = names.join(', ')The table instance is a model; markup, CSS, semantics, and accessibility are renderer responsibilities.
Source: docs/overview.md
Wrong:
const options = () => ({
data: source.map((item) => item),
columns: helper.columns([]),
})Correct:
const data = source.map((item) => item)
const columns = helper.columns([])
const options = () => ({ data, columns })New references invalidate memoized row and column work and can create adapter render loops.
Source: docs/guide/data.md
Wrong:
const { getValue } = table.getRowModel().rows[0]!
getValue('name')Correct:
const row = table.getRowModel().rows[0]!
row.getValue('name')V9 row, cell, column, and header methods use their instance as this.
Source: docs/framework/react/guide/migrating.md#instance-methods-must-be-called-on-their-instance
Wrong:
const rowNumber = row._displayIndexCache + 1Correct:
const displayIndex = row.getDisplayIndex()
const rowNumber = displayIndex === -1 ? undefined : displayIndex + 1_displayIndexCache is internal and may be stale until display order is recomputed. The public method refreshes display order, validates that the cached slot still contains the row, and returns -1 when it does not.
Source: docs/guide/rows.md#row-numbers-and-display-indexes, packages/table-core/src/core/rows/coreRowsFeature.utils.ts
Inspect node_modules/@tanstack/table-core/dist/index.d.ts, then follow the exported implementation. For UI creation and rendering, inspect node_modules/@tanstack/<framework>-table/dist/index.d.ts and load that adapter's getting-started skill.
9e523bc
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.