Preserve nested identity
A query receives a freshly parsed response whose unchanged nested records should retain their old references.
TanStack · Function
Returns the previous value when it is deeply equal to the new value; otherwise, it reuses equal nested parts from the previous value. This supports structural sharing for JSON-like data.
replaceEqualDeep compares a previous value with a new value recursively. It returns the previous value when the two are deeply equal; otherwise, it builds the new result while reusing deeply equal nested parts from the previous value, which supports structural sharing for JSON-like data.
function replaceEqualDeep<T>(a: unknown, b: T, depth?: number): T;| Name | Type | Description |
|---|---|---|
a | unknown | The previous value, whose deeply equal parts are reused. |
b | T | The new value. |
depth | number | The current recursion depth. Past a depth of 500, b is returned as is. |
T — a if b is deeply equal to it, otherwise b with its deeply equal parts replaced by those of a.
import { replaceEqualDeep } from '@tanstack/query-core'
const previous = { user: { id: 1, name: 'Ada' }, count: 1 }
const next = { user: { id: 1, name: 'Ada' }, count: 2 }
const result = replaceEqualDeep(previous, next)
console.log(result !== previous) // true
console.log(result.user === previous.user) // true
console.log(result.count) // 2Reuses the unchanged nested user object while retaining the new count.
A query receives a freshly parsed response whose unchanged nested records should retain their old references.
A cache or state update needs a new top-level result while avoiding needless replacement of equal subtrees.
Recursive comparison of JSON-compatible query data should share unchanged branches.
It accepts a previous value and a new value, then returns the previous value when they are deeply equal. When they differ, unchanged deeply equal children from the previous value are reused in the returned new value.
Follow-up: What happens with very deeply nested input? The documented recursion depth limit means that after depth 500, the new value is returned as-is.
The first parameter is the previous value and may be unknown. The second parameter is the new value and determines the generic return type T; the optional third parameter represents the current recursion depth.
Follow-up: Why can the first parameter be unknown? The function only requires it as a source of potentially reusable deeply equal parts, while the returned shape is typed from the new value.
It is useful for structural sharing between JSON values. Reusing unchanged references can preserve identity for unaffected subtrees and avoid treating those subtrees as changed.
Follow-up: What should be considered before applying it to arbitrary data? The documentation specifically describes JSON values, so non-JSON structures should not be assumed to receive equivalent handling.
structural sharingquery-corereplaceEqualDeep