UNPKG

@tanstack/table-core

Version:

Headless UI for building powerful tables & datagrids for TS/JS.

176 lines (127 loc) 4.76 kB
--- name: core description: > 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. metadata: type: core library: '@tanstack/table-core' library_version: '9.0.0' sources: - 'TanStack/table:docs/overview.md' - 'TanStack/table:docs/guide/tables.md' - 'TanStack/table:docs/guide/data.md' - 'TanStack/table:docs/guide/rows.md' - 'TanStack/table:packages/table-core/src/index.ts' --- # 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 <!-- skill-snippet:check --> ```ts 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 ```ts 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 ```ts 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 ```ts 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: ```ts document.body.append(table as unknown as Node) ``` Correct: ```ts 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: ```ts const options = () => ({ data: source.map((item) => item), columns: helper.columns([]), }) ``` Correct: ```ts 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: ```ts const { getValue } = table.getRowModel().rows[0]! getValue('name') ``` Correct: ```ts 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: ```ts const rowNumber = row._displayIndexCache + 1 ``` Correct: ```ts 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.