Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .changeset/central-noop-state-guard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
'@tanstack/table-core': patch
---

Centralize state updates behind a `setStateSlice` util with an optional structural no-op policy. Equality-guarded slices give their state owner a functional updater that resolves against the owner's latest value and returns the existing reference when nothing changed. Atom and framework state owners can then skip the write and re-render without comparing against a potentially stale controlled table snapshot.

This removes an entire class of render loops where an auto reset (for example `autoResetExpanded` after a `data` reference change) fired a change handler with a freshly allocated but semantically identical value, causing controlled-state consumers to re-render, produce a new `data` reference, and loop.

Behavior notes:

- A custom `onXChange` handler is still invoked for an apparent no-op. Only its state container knows the latest queued value, so it performs the equality check when it applies the guarded updater. This preserves same-tick update composition in frameworks such as React.
- State updaters are evaluated once, by the state owner. Controlled fallback atoms therefore remain correct if control is later released, and external atom owners do not run functional updaters twice.
- `stateSlicesEqual` compares enumerable string and symbol keys through the three container levels used by stock state. Sparse arrays remain distinct from explicit `undefined` entries; deeper or non-plain values compare by reference and safely allow the update.
- Structural equality is opt-in per slice. Opaque `globalFilter` values and row-scaled `rowSelection`/`rowPinning` maps stay direct. The high-frequency `columnSizing`, `columnResizing`, and ordinary cell-selection write paths also avoid a comparison on every pointer update.
- Auto-reset-prone cell selection applies equality specifically to resets, while its drag handler keeps an O(1) active-focus guard. Expanded state similarly guards reset/auto-reset while ordinary writes stay direct, and toggle-all keeps its explicit O(1) no-op checks.
2 changes: 1 addition & 1 deletion docs/reference/index/functions/assignPrototypeAPIs.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function assignPrototypeAPIs<TFeatures, TData, TDeps, TDepArgs>(
apis): void;
```

Defined in: [utils.ts:453](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L453)
Defined in: [utils.ts:586](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L586)

Assigns API methods to a prototype object for memory-efficient method sharing.
All instances created with this prototype will share the same method references.
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/functions/assignTableAPIs.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function assignTableAPIs<TFeatures, TData, TDeps, TDepArgs>(
apis): void;
```

Defined in: [utils.ts:411](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L411)
Defined in: [utils.ts:544](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L544)

Assigns Table API methods directly to the table instance.
Unlike row/cell/column/header, the table is a singleton so methods are assigned directly.
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/functions/callMemoOrStaticFn.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function callMemoOrStaticFn<TObject, TArgs, TReturn>(
args): TReturn;
```

Defined in: [utils.ts:499](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L499)
Defined in: [utils.ts:632](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L632)

Looks to run the memoized function with the builder pattern on the object if it exists, otherwise fall back to the static method passed in.

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/functions/flattenBy.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: flattenBy
function flattenBy<TNode>(arr, getChildren): TNode[];
```

Defined in: [utils.ts:131](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L131)
Defined in: [utils.ts:264](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L264)

Flattens a tree of nodes by recursively reading child nodes.

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/functions/getFunctionNameInfo.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: getFunctionNameInfo
function getFunctionNameInfo(staticFnName, splitBy): object;
```

Defined in: [utils.ts:394](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L394)
Defined in: [utils.ts:527](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L527)

Assumes that a function name is in the format of `parentName_fnKey` and returns the `fnKey` and `fnName` in the format of `parentName.fnKey`.

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/functions/isFunction.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: isFunction
function isFunction<T>(d): d is T;
```

Defined in: [utils.ts:122](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L122)
Defined in: [utils.ts:255](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L255)

Returns whether a value is a function.

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/functions/memo.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: memo
function memo<TDeps, TDepArgs, TResult>(__namedParameters): (depArgs?) => TResult;
```

Defined in: [utils.ts:166](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L166)
Defined in: [utils.ts:299](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L299)

Creates a dependency-tracked memoized function for table internals.

Expand Down
66 changes: 66 additions & 0 deletions docs/reference/index/functions/setStateSlice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
id: setStateSlice
title: setStateSlice
---

# Function: setStateSlice()

```ts
function setStateSlice<K>(
instance,
key,
updater,
isEqual): void;
```

Defined in: [utils.ts:223](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L223)

Routes a state slice update through the slice's `on<State>Change` handler,
preserving the owner's current reference for structural no-ops.

Equality is evaluated inside the updater received by the state owner, never
against the table's potentially stale controlled snapshot. This keeps
same-tick updates composable in queued host containers such as React state,
evaluates the original updater only when the owner applies it, and lets atom
owners suppress notifications by returning their existing reference.

A user-provided change handler is still invoked for a no-op because only that
handler's state container can know its latest queued value. The guarded
updater returns that container's previous reference, preventing a state write
or render in state containers with identity bailout semantics.

Hot-path slices that skip guarding entirely (selection maps that scale with
row count, pointer-frequency resize state) call their change handler
directly instead of routing through this util. Custom feature slices with a
cheaper or semantic-aware comparison can pass `isEqual` to override the
structural default.

## Type Parameters

### K

`K` *extends* `string` & `object` \| keyof TableState\_All

## Parameters

### instance

#### options

`object`

### key

`K`

### updater

[`Updater`](../type-aliases/Updater.md)\<`StateSliceForKey`\<`K`\>\>

### isEqual

[`StateSliceEqualityFn`](../type-aliases/StateSliceEqualityFn.md)\<`StateSliceForKey`\<`K`\>\> = `stateSlicesEqual`

## Returns

`void`
2 changes: 1 addition & 1 deletion docs/reference/index/functions/skipFirstRun.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: skipFirstRun
function skipFirstRun(fn): () => void;
```

Defined in: [utils.ts:217](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L217)
Defined in: [utils.ts:350](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L350)

Wraps a callback so that its first invocation is skipped.

Expand Down
34 changes: 34 additions & 0 deletions docs/reference/index/functions/stateSlicesEqual.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
id: stateSlicesEqual
title: stateSlicesEqual
---

# Function: stateSlicesEqual()

```ts
function stateSlicesEqual(a, b): boolean;
```

Defined in: [utils.ts:155](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L155)

Structurally compares two state slice values as deeply as stock feature
state can nest and no deeper.

Three container levels cover flat maps and arrays, arrays of state objects,
array-valued filter values, and `columnResizing.columnSizingStart` tuples.
Deeper containers and non-plain values compare by reference. A `false`
result is always safe: the state update simply proceeds.

## Parameters

### a

`unknown`

### b

`unknown`

## Returns

`boolean`
2 changes: 1 addition & 1 deletion docs/reference/index/functions/tableMemo.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: tableMemo
function tableMemo<TFeatures, TDeps, TDepArgs, TResult>(__namedParameters): (depArgs?) => TResult;
```

Defined in: [utils.ts:254](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L254)
Defined in: [utils.ts:387](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L387)

Creates a table-aware memoized function.

Expand Down
3 changes: 3 additions & 0 deletions docs/reference/index/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ title: index
- [SortDirection](type-aliases/SortDirection.md)
- [SortFnOption](type-aliases/SortFnOption.md)
- [SortingState](type-aliases/SortingState.md)
- [StateSliceEqualityFn](type-aliases/StateSliceEqualityFn.md)
- [StringOrTemplateHeader](type-aliases/StringOrTemplateHeader.md)
- [Table](type-aliases/Table.md)
- [Table\_RowModels](type-aliases/Table_RowModels.md)
Expand Down Expand Up @@ -413,7 +414,9 @@ title: index
- [makeStateUpdater](functions/makeStateUpdater.md)
- [memo](functions/memo.md)
- [metaHelper](functions/metaHelper.md)
- [setStateSlice](functions/setStateSlice.md)
- [skipFirstRun](functions/skipFirstRun.md)
- [stateSlicesEqual](functions/stateSlicesEqual.md)
- [tableFeatures](functions/tableFeatures.md)
- [tableMemo](functions/tableMemo.md)
- [tableOptions](functions/tableOptions.md)
6 changes: 3 additions & 3 deletions docs/reference/index/interfaces/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: API

# Interface: API\<_TDeps, _TDepArgs\>

Defined in: [utils.ts:381](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L381)
Defined in: [utils.ts:514](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L514)

## Type Parameters

Expand All @@ -25,7 +25,7 @@ Defined in: [utils.ts:381](https://github.com/TanStack/table/blob/main/packages/
fn: (...args) => any;
```

Defined in: [utils.ts:382](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L382)
Defined in: [utils.ts:515](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L515)

#### Parameters

Expand All @@ -45,7 +45,7 @@ Defined in: [utils.ts:382](https://github.com/TanStack/table/blob/main/packages/
optional memoDeps: (depArgs?) => any[] | undefined;
```

Defined in: [utils.ts:383](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L383)
Defined in: [utils.ts:516](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L516)

#### Parameters

Expand Down
6 changes: 3 additions & 3 deletions docs/reference/index/interfaces/PrototypeAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ title: PrototypeAPI

# Interface: PrototypeAPI\<_TDeps, _TDepArgs\>

Defined in: [utils.ts:436](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L436)
Defined in: [utils.ts:569](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L569)

## Type Parameters

Expand All @@ -25,7 +25,7 @@ Defined in: [utils.ts:436](https://github.com/TanStack/table/blob/main/packages/
fn: (self, ...args) => any;
```

Defined in: [utils.ts:437](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L437)
Defined in: [utils.ts:570](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L570)

#### Parameters

Expand All @@ -49,7 +49,7 @@ Defined in: [utils.ts:437](https://github.com/TanStack/table/blob/main/packages/
optional memoDeps: (self, depArgs?) => any[] | undefined;
```

Defined in: [utils.ts:438](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L438)
Defined in: [utils.ts:571](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L571)

#### Parameters

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/type-aliases/APIObject.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: APIObject
type APIObject<TDeps, TDepArgs> = Record<string, API<TDeps, TDepArgs>>;
```

Defined in: [utils.ts:386](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L386)
Defined in: [utils.ts:519](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L519)

## Type Parameters

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/index/type-aliases/PrototypeAPIObject.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: PrototypeAPIObject
type PrototypeAPIObject<TDeps, TDepArgs> = Record<string, PrototypeAPI<TDeps, TDepArgs>>;
```

Defined in: [utils.ts:441](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L441)
Defined in: [utils.ts:574](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L574)

## Type Parameters

Expand Down
32 changes: 32 additions & 0 deletions docs/reference/index/type-aliases/StateSliceEqualityFn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
id: StateSliceEqualityFn
title: StateSliceEqualityFn
---

# Type Alias: StateSliceEqualityFn()\<T\>

```ts
type StateSliceEqualityFn<T> = (current, next) => boolean;
```

Defined in: [utils.ts:200](https://github.com/TanStack/table/blob/main/packages/table-core/src/utils.ts#L200)

## Type Parameters

### T

`T`

## Parameters

### current

`T`

### next

`T`

## Returns

`boolean`
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: cell_getCanSelect
function cell_getCanSelect<TFeatures, TData, TValue>(cell): boolean;
```

Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:507](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L507)
Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:515](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L515)

Checks whether this cell can currently be selected.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: cell_getIsFocused
function cell_getIsFocused<TFeatures, TData, TValue>(cell): boolean;
```

Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:605](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L605)
Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:613](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L613)

Checks whether this cell is the active cell.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: cell_getIsSelected
function cell_getIsSelected<TFeatures, TData, TValue>(cell): boolean;
```

Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:581](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L581)
Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:589](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L589)

Checks whether this cell falls inside the final positive selection.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: cell_getSelectionEdges
function cell_getSelectionEdges<TFeatures, TData, TValue>(cell): CellSelectionEdges;
```

Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:649](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L649)
Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:657](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L657)

Returns which sides of this cell sit on the outer boundary of the selection.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: cell_getSelectionExtendHandler
function cell_getSelectionExtendHandler<TFeatures, TData, TValue>(cell): (_e) => void;
```

Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:1482](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L1482)
Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:1490](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L1490)

Creates a handler that extends the active range to this cell during a drag.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: cell_getSelectionStartHandler
function cell_getSelectionStartHandler<TFeatures, TData, TValue>(cell, _contextDocument?): (e) => void;
```

Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:1403](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L1403)
Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:1411](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L1411)

Creates a handler that begins a selection at this cell.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: cell_getTabIndex
function cell_getTabIndex<TFeatures, TData, TValue>(cell): number;
```

Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:629](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L629)
Defined in: [features/cell-selection/cellSelectionFeature.utils.ts:637](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/cell-selection/cellSelectionFeature.utils.ts#L637)

Returns `0` for the focused cell and `-1` otherwise, for roving tabindex.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ title: column_clearSorting
function column_clearSorting<TFeatures, TData, TValue>(column): void;
```

Defined in: [features/row-sorting/rowSortingFeature.utils.ts:510](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/row-sorting/rowSortingFeature.utils.ts#L510)
Defined in: [features/row-sorting/rowSortingFeature.utils.ts:512](https://github.com/TanStack/table/blob/main/packages/table-core/src/features/row-sorting/rowSortingFeature.utils.ts#L512)

Removes this column from the sorting state.

Expand Down
Loading
Loading