CtrlK
BlogDocsLog inGet started
Tessl Logo

getting-started

Create and render a TanStack React Table v9 table with useTable, tableFeatures, stable data and columns, row/header models, and table.FlexRender. Load for a first React table, headless rendering, or when v8 useReactTable examples are producing the wrong setup.

72

Quality

91%

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

This skill builds on @tanstack/table-core#core and @tanstack/table-core#table-features. Read them first for the headless model and explicit feature registration.

Setup

import { useMemo, useState } from 'react'
import {
  createColumnHelper,
  tableFeatures,
  useTable,
} from '@tanstack/react-table'

type Person = { name: string; age: number }
const features = tableFeatures({})
const helper = createColumnHelper<typeof features, Person>()
const columns = helper.columns([
  helper.accessor('name', { header: 'Name' }),
  helper.accessor('age', { header: 'Age' }),
])

export function PeopleTable() {
  const [data] = useState<Person[]>([{ name: 'Ada', age: 36 }])
  const table = useTable({ features, columns, data })

  return (
    <table>
      <thead>
        {table.getHeaderGroups().map((group) => (
          <tr key={group.id}>
            {group.headers.map((header) => (
              <th key={header.id}>
                {header.isPlaceholder ? null : (
                  <table.FlexRender header={header} />
                )}
              </th>
            ))}
          </tr>
        ))}
      </thead>
      <tbody>
        {table.getRowModel().rows.map((row) => (
          <tr key={row.id}>
            {row.getAllCells().map((cell) => (
              <td key={cell.id}>
                <table.FlexRender cell={cell} />
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    </table>
  )
}

Table produces models and state; React owns the semantic markup, styles, event affordances, and accessibility.

Core Patterns

Add only the feature the table uses

import {
  createSortedRowModel,
  rowSortingFeature,
  tableFeatures,
} from '@tanstack/react-table'

const sortableFeatures = tableFeatures({
  rowSortingFeature,
  sortedRowModel: createSortedRowModel(),
})

Row-model slots belong inside tableFeatures, after their prerequisite feature.

Keep static inputs outside render

const features = tableFeatures({})
const data: Person[] = [{ name: 'Ada', age: 36 }]

Use state, memoization, or query results for changing data; avoid a new fallback array every render.

Common Mistakes

HIGH Copying the v8 table constructor

Wrong:

const table = useReactTable({
  data,
  columns,
  getCoreRowModel: getCoreRowModel(),
})

Correct:

const table = useTable({ data, columns, features })

V9 uses useTable; optional row models are registered as feature slots rather than table options.

Source: docs/framework/react/guide/migrating.md

HIGH Assuming feature APIs are global

Wrong:

const features = tableFeatures({})

Correct:

const features = tableFeatures({
  rowSortingFeature,
  sortedRowModel: createSortedRowModel(),
})

Sorting state and methods do not exist until the sorting feature is registered.

Source: packages/table-core/src/TableFeatures.ts

MEDIUM Recreating fallback data each render

Wrong:

const table = useTable({ features, columns, data: response.data ?? [] })

Correct:

// module scope
const EMPTY_DATA: Person[] = []
const table = useTable({ features, columns, data: response.data ?? EMPTY_DATA })

A fresh fallback invalidates data-dependent models on every render.

Source: docs/framework/react/guide/data.md

API Discovery

Inspect node_modules/@tanstack/react-table/dist/index.d.ts first, then the exported useTable.d.ts, FlexRender.d.ts, or core feature source. Use installed declarations so names match the consumer's exact v9 version.

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.