npm / @tanstack/vue-table
@tanstack/vue-table
What changed in @tanstack/vue-table 9, from its official release notes, upgrade guides and advisories. Sources checked 2026-10-19.
64 breaking2 deprecations29 new APIs and options1 performance2 behavior and defaults4 fixes and other
See which of these apply to your code, ranked, in your agent:
npx @unstale/cli init@tanstack/vue-table 9102 changes
Breaking changes 64
Bundled Intent skills now use smaller entry points with task-specific references; consumers with individual skill permissions or explicit agent mappings must replace retired IDs and refresh their mappings.
The callable AggregationFn and CreatedAggregationFn types were replaced by AggregationFnDef.
Register aggregation functions in the aggregationFns slot to use string references, replacing module augmentation.
The region argument now uses end instead of right.
column.getAggregationFn() was renamed because a column can run multiple aggregation definitions.
The method now takes one options object containing rows and maxDepth instead of positional arguments.
The column.getAutoSortingFn() method was renamed to column.getAutoSortFn().
The region argument now uses start/end instead of left/right.
The pinned-position result now uses start/end instead of left/right.
The column.getSortingFn() method was renamed to column.getSortFn().
The region argument now uses start instead of left.
Use start and end rather than left and right when pinning a column.
Global declaration merging still works, but ColumnMeta now takes TFeatures as its first generic parameter.
Column pinning state now uses logical start/end regions instead of left/right; there are no deprecated aliases.
Column pinning state now uses logical start/end regions instead of left/right; there are no deprecated aliases.
Column pinning now uses start/end terminology instead of the previous terminology.
The former columnSizingInfo state is now named columnResizing.
Interactive resizing is now a separate feature; import it alongside columnSizingFeature when drag-to-resize is needed.
Rename columnSizingInfo state to columnResizing, including related options.
Custom aggregation callables now use context-based definitions constructed with constructAggregationFn.
createColumnHelper now takes TFeatures before TData.
The combined enablePinning option was split into separate column-pinning and row-pinning options.
Replace enablePinning with enableColumnPinning or enableRowPinning.
Set this option to false to preserve the previous non-range handler behavior.
Compiled output now targets ES2022.
Packages ship as modern ESM; UMD and CJS builds are dropped.
Tables must explicitly declare their features through the new required features option; registering only needed features enables tree-shaking.
Register filter functions in the features registry slot to make string references typecheck, replacing FilterFns module augmentation.
Use the filterMeta registry slot to type filter metadata instead of augmenting FilterMeta.
Move get*RowModel() options to tableFeatures slots; row model factories no longer take arguments.
This column option controls which depth-selected rows are provided to aggregation; the default 0 preserves direct-child aggregation, while Infinity selects terminal leaf rows.
The onColumnSizingInfoChange option was renamed to onColumnResizingChange.
The table option was removed; subscribe to table.store to listen for any state change, while per-slice change handlers remain available.
Row model factories and filter, sort, and aggregation function registries are registered through tableFeatures rather than separate table options.
The row API for visible cells on the right was renamed to use logical end terminology.
The row API for visible cells on the left was renamed to use logical start terminology.
Aggregation is an independent feature; explicitly registered features must include rowAggregationFeature when columns use aggregation APIs.
RowData is now restricted to Record<string, any> or Array<any>, so unusual data types must conform to one of those shapes.
setColumnSizingInfo() was renamed to setColumnResizing().
The column definition option sortingFn was renamed to sortFn; update column definitions to use the new name.
The SortingFn type was renamed to SortFn.
The SortingFns interface was renamed to SortFns.
The built-in sorting functions identifier sortingFns was renamed to sortFns.
Register sort functions in the sortFns slot to use string references, replacing module augmentation.
Rename sortingFn to sortFn in column definitions.
This internal table API has been removed.
This internal table API has been removed.
This internal table API has been removed.
This internal table API has been removed.
The header-groups API for the right region was renamed to use logical end terminology.
The leaf-columns API for the right region was renamed to use logical end terminology.
The total-size API for the right region was renamed to use logical end terminology.
The visible leaf-columns API for the right region was renamed to use logical end terminology.
Now returns true whenever at least one page row is selected, including when all page rows are selected.
Now returns true whenever at least one row is selected, including when all rows are selected.
The header-groups API for the left region was renamed to use logical start terminology.
The leaf-columns API for the left region was renamed to use logical start terminology.
The total-size API for the left region was renamed to use logical start terminology.
The visible leaf-columns API for the left region was renamed to use logical start terminology.
Access state through table.store.state or table.state instead of table.getState().
Provides the selected table state directly; by default it contains all registered state, while a custom selector can limit its shape.
Global declaration merging still works, but TableMeta now takes TFeatures as its first generic parameter.
Most table types now take TFeatures as a generic parameter, which should be supplied when typing tables, columns, rows, and cells.
Use useTable in place of useReactTable for creating a table.
Deprecations 2
Deprecated in the Vue adapter; read table APIs or atoms in native Vue reactive contexts, and use a child component when a separate render boundary is needed. The wrapper remains for compatibility.
The full function registry export is deprecated in favor of importing and registering only the individual functions in use.
New APIs and options 29
Pass writable atoms for individual state slices; table reads and writes use those atoms, which take precedence over matching state options and are not cleared by table.reset().
Pass writable atoms through the atoms option to own specific state slices externally.
Adds spreadsheet-style rectangular cell-range selection, including drag selection, Shift-extend, and multiple disjoint ranges.
Adds body-cell spanning across rows and columns, with span-aware selection and header row-span computation.
Column grouping is separate from aggregation and is needed only when rows are also grouped.
Wrap column arrays with columns() to preserve each column's TValue type, including through nested group columns.
A type-only columnMeta slot on the features option lets you declare metadata types per table without declaration merging.
Column sizing is now a separate feature, allowing fixed-width tables to import sizing without interactive resizing.
Convert custom aggregation callables to constructAggregationFn({ aggregate, merge? }) definitions.
Creates a reusable custom hook with pre-bound configuration for applications whose tables share features, row models, options, or components.
Components registered via createTableHook can access table, header, and cell context through context hooks.
Row pinning now has its own option, separate from column pinning.
A component can render header, cell, or footer templates as an alternative to the existing flexRender function.
Lets callers provide writable atoms for state slices they want to own externally.
The public row.getAllCellsByColumnId() method replaces the previously private row._getAllCellsByColumnId().
Adds a row API for obtaining its display index.
Provides all features for Table V8-like behavior, as an alternative to registering features individually.
Use StockFeatures as the feature type when using stockFeatures with useTable.
Exposes readonly atoms for individual state slices, allowing fine-grained subscriptions.
Subscribe to individual state slices via table.atoms.<slice> and useSelector for narrower re-renders.
A component attached to the table instance renders header, cell, or footer templates as an alternative to flexRender.
Adds a table API for obtaining the maximum sub-row depth.
Exposes a framework-agnostic store for reading the full table state and subscribing to state changes.
Optionally use table.Subscribe for render optimizations.
Registers table features, row models, and processing function registries, enabling feature prerequisite type checks and tree-shaking.
Define table features with tableFeatures(), or use stockFeatures, and migrate get*RowModel() options to feature slots.
A type-only tableMeta slot on the features option lets you declare metadata types per table without declaration merging.
Provides type-safe composition of reusable table options and allows partial configurations to omit required fields.
Use tableOptions() for composable configurations.
Performance 1
Per-slice atoms can be used as narrow subscription sources, avoiding re-renders and full state snapshot construction for unrelated state changes.
Behavior and default changes 2
When rowSelectionFeature is enabled, the handler now supports inclusive Shift range selection by default; direct row.toggleSelected() calls are unchanged.
TanStack Table v9 is released as stable, with upgrade instructions available in the migration guide.
Fixes and other changes 4
AppCell now reads the current cell prop when a keyed loop reuses its wrapper, preventing stale snippet, slot, and useCellContext() values.
AppFooter now reads the current footer prop when a keyed loop reuses its wrapper, preventing stale values.
AppHeader now reads the current header prop when a keyed loop reuses its wrapper, preventing stale snippet, slot, and useHeaderContext() values.
Methods are shared on prototypes, so destructuring them loses the required this context; call them on their original instance.