CtrlK
BlogDocsLog inGet started
Tessl Logo

core

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

Quality

80%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Passed

No findings from the security scan

SKILL.md
Quality
Evals
Security

TanStack Table Core

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.

Setup

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()))
}

Core Patterns

Start with core, add only behavior used

const features = tableFeatures({
  coreReactivityFeature: storeReactivityBindings(),
})

The core row model is automatic; filtering, sorting, pagination, and other optional behavior require their feature plugins.

Keep model inputs stable

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.

Number rows in current display order

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.

Common Mistakes

[HIGH] Expecting Table to render a grid

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

[HIGH] Recreating model inputs repeatedly

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

[HIGH] Detaching prototype-bound methods

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

[HIGH] Reading the display-index cache directly

Wrong:

const rowNumber = row._displayIndexCache + 1

Correct:

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

API Discovery

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.

Repository
TanStack/table
Last updated
First committed

Is this your skill?

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.