Capítulo 6 de 54

Chapter 6: Migrating to TanStack Table V9 (React)

Core Idea

V9 keeps the headless model, column definitions, and rendering pattern from v8 — the actual breaking change is how you define a table: useReactTable becomes useTable, and tables now require an explicit features option (from tableFeatures({...})) instead of importing row-model getters ad hoc.

Key Concepts

  • Hook rename: useReactTable(options)useTable(options), matching hook naming across all TanStack libraries.
  • New required features option: pass the object returned by tableFeatures({...}), listing which optional features (and their row model factories: sortedRowModel, filteredRowModel, paginationRowModel, etc.) this table actually uses. An empty tableFeatures({}) is valid — core-only, no opt-in features.
  • State is now TanStack Store-backed: enables correct behavior under the React Compiler (see React Compiler Guide) and fine-grained subscriptions via table.atoms / table.store / table.state / table.Subscribe — but the old state + on[State]Change pattern still works unchanged, so this is backward compatible.
  • Per-table meta types (tableMeta, columnMeta, filterMeta) replace v8's global interface declaration merging — no more augmenting a shared global type just to type one table's meta.
  • Feature-gated APIs: an API (e.g. column.getIsSorted()) only exists on the type if its feature is registered in tableFeatures(); the type system validates feature prerequisites.
  • Tree shaking: only the features/row models you register ship in the bundle — a sort-only table doesn't bundle filtering or pagination code. A base table starts around 5kb.
  • New/refreshed features: Cell Selection (cellSelectionFeature) and Cell Spanning (cellSpanningFeature) are new in v9; Aggregation, Row Selection, Column Pinning, and Column Resizing got materially more capable (multi-aggregation per column, Shift-range selection, logical start/end pinning).
  • Modern builds: ESM-only (no more UMD/CJS), TS target ES2022, no src/source maps shipped in the published package (smaller install).
  • Most upgrades are opt-in: doing nothing special still works like v8 (default selectors select all registered state); import { stockFeatures } includes every feature at once, matching v8's "everything on" behavior if you don't want to think about tree-shaking yet. Table markup itself (<table>/<thead>/<tr>/<td>) is unchanged.

Reference Tables

v8v9
useReactTable(options)useTable(options)
import row-model getters directly (getCoreRowModel(), etc.) and pass via getXRowModel optionsregister feature + row-model factory together inside tableFeatures({...}), pass as features
global declaration merging for TableMeta/ColumnMetaper-table tableMeta/columnMeta/filterMeta type slots
UMD/CJS + ESM buildsESM-only
all APIs always present on the typeonly APIs for registered features are present on the type

Key Takeaways

  1. The rename (useReactTableuseTable) plus the new required features option are the two changes that break every existing table — everything else (markup, most APIs) is additive or backward compatible.
  2. If migrating incrementally is too disruptive right now, useLegacyTable (from @tanstack/react-table/legacy) accepts the v8-style API while running on v9 internals — see the dedicated chapter, but treat it as temporary: it's deprecated and bundles every feature by default.
  3. stockFeatures is the fastest path to "make it compile like v8 did" — swap in individual feature registration later once things are green.
  4. State management changes are opt-in: you don't have to touch table.atoms/table.Subscribe to migrate; the old state/on[State]Change props still work.

Connects To

  • Using useLegacyTable for Incremental Migration: the deprecated compatibility shim referenced above.
  • Quick Start (React): what a from-scratch v9 table looks like without any v8 baggage.
  • React Compiler Guide: why the TanStack Store-backed state system matters for compiler compatibility.
  • Legacy API (v8 Compatibility): the full legacy-namespace API reference.