@tanstack/query-core 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/focusManager.js +101 -0
- package/build/cjs/focusManager.js.map +1 -0
- package/build/cjs/hydration.js +112 -0
- package/build/cjs/hydration.js.map +1 -0
- package/build/cjs/index.js +51 -0
- package/build/cjs/index.js.map +1 -0
- package/build/cjs/infiniteQueryBehavior.js +160 -0
- package/build/cjs/infiniteQueryBehavior.js.map +1 -0
- package/build/cjs/infiniteQueryObserver.js +92 -0
- package/build/cjs/infiniteQueryObserver.js.map +1 -0
- package/build/cjs/logger.js +18 -0
- package/build/cjs/logger.js.map +1 -0
- package/build/cjs/mutation.js +258 -0
- package/build/cjs/mutation.js.map +1 -0
- package/build/cjs/mutationCache.js +99 -0
- package/build/cjs/mutationCache.js.map +1 -0
- package/build/cjs/mutationObserver.js +130 -0
- package/build/cjs/mutationObserver.js.map +1 -0
- package/build/cjs/notifyManager.js +114 -0
- package/build/cjs/notifyManager.js.map +1 -0
- package/build/cjs/onlineManager.js +100 -0
- package/build/cjs/onlineManager.js.map +1 -0
- package/build/cjs/queriesObserver.js +170 -0
- package/build/cjs/queriesObserver.js.map +1 -0
- package/build/cjs/query.js +474 -0
- package/build/cjs/query.js.map +1 -0
- package/build/cjs/queryCache.js +140 -0
- package/build/cjs/queryCache.js.map +1 -0
- package/build/cjs/queryClient.js +357 -0
- package/build/cjs/queryClient.js.map +1 -0
- package/build/cjs/queryObserver.js +521 -0
- package/build/cjs/queryObserver.js.map +1 -0
- package/build/cjs/removable.js +47 -0
- package/build/cjs/removable.js.map +1 -0
- package/build/cjs/retryer.js +177 -0
- package/build/cjs/retryer.js.map +1 -0
- package/build/cjs/subscribable.js +43 -0
- package/build/cjs/subscribable.js.map +1 -0
- package/build/cjs/utils.js +356 -0
- package/build/cjs/utils.js.map +1 -0
- package/build/esm/index.js +3077 -0
- package/build/esm/index.js.map +1 -0
- package/build/stats-html.html +2689 -0
- package/build/umd/index.development.js +3106 -0
- package/build/umd/index.development.js.map +1 -0
- package/build/umd/index.production.js +12 -0
- package/build/umd/index.production.js.map +1 -0
- package/package.json +25 -0
- package/src/focusManager.ts +89 -0
- package/src/hydration.ts +164 -0
- package/src/index.ts +35 -0
- package/src/infiniteQueryBehavior.ts +214 -0
- package/src/infiniteQueryObserver.ts +159 -0
- package/src/logger.native.ts +11 -0
- package/src/logger.ts +9 -0
- package/src/mutation.ts +349 -0
- package/src/mutationCache.ts +157 -0
- package/src/mutationObserver.ts +195 -0
- package/src/notifyManager.ts +96 -0
- package/src/onlineManager.ts +89 -0
- package/src/queriesObserver.ts +211 -0
- package/src/query.ts +612 -0
- package/src/queryCache.ts +206 -0
- package/src/queryClient.ts +716 -0
- package/src/queryObserver.ts +748 -0
- package/src/removable.ts +37 -0
- package/src/retryer.ts +215 -0
- package/src/subscribable.ts +33 -0
- package/src/tests/focusManager.test.tsx +155 -0
- package/src/tests/hydration.test.tsx +429 -0
- package/src/tests/infiniteQueryBehavior.test.tsx +124 -0
- package/src/tests/infiniteQueryObserver.test.tsx +64 -0
- package/src/tests/mutationCache.test.tsx +260 -0
- package/src/tests/mutationObserver.test.tsx +75 -0
- package/src/tests/mutations.test.tsx +363 -0
- package/src/tests/notifyManager.test.tsx +51 -0
- package/src/tests/onlineManager.test.tsx +148 -0
- package/src/tests/queriesObserver.test.tsx +330 -0
- package/src/tests/query.test.tsx +888 -0
- package/src/tests/queryCache.test.tsx +236 -0
- package/src/tests/queryClient.test.tsx +1435 -0
- package/src/tests/queryObserver.test.tsx +802 -0
- package/src/tests/utils.test.tsx +360 -0
- package/src/types.ts +705 -0
- package/src/utils.ts +435 -0
package/src/utils.ts
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
import type { Mutation } from './mutation'
|
|
2
|
+
import type { Query } from './query'
|
|
3
|
+
import type {
|
|
4
|
+
FetchStatus,
|
|
5
|
+
MutationFunction,
|
|
6
|
+
MutationKey,
|
|
7
|
+
MutationOptions,
|
|
8
|
+
QueryFunction,
|
|
9
|
+
QueryKey,
|
|
10
|
+
QueryOptions,
|
|
11
|
+
} from './types'
|
|
12
|
+
|
|
13
|
+
// TYPES
|
|
14
|
+
|
|
15
|
+
export interface QueryFilters {
|
|
16
|
+
/**
|
|
17
|
+
* Filter to active queries, inactive queries or all queries
|
|
18
|
+
*/
|
|
19
|
+
type?: QueryTypeFilter
|
|
20
|
+
/**
|
|
21
|
+
* Match query key exactly
|
|
22
|
+
*/
|
|
23
|
+
exact?: boolean
|
|
24
|
+
/**
|
|
25
|
+
* Include queries matching this predicate function
|
|
26
|
+
*/
|
|
27
|
+
predicate?: (query: Query) => boolean
|
|
28
|
+
/**
|
|
29
|
+
* Include queries matching this query key
|
|
30
|
+
*/
|
|
31
|
+
queryKey?: QueryKey
|
|
32
|
+
/**
|
|
33
|
+
* Include or exclude stale queries
|
|
34
|
+
*/
|
|
35
|
+
stale?: boolean
|
|
36
|
+
/**
|
|
37
|
+
* Include queries matching their fetchStatus
|
|
38
|
+
*/
|
|
39
|
+
fetchStatus?: FetchStatus
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface MutationFilters {
|
|
43
|
+
/**
|
|
44
|
+
* Match mutation key exactly
|
|
45
|
+
*/
|
|
46
|
+
exact?: boolean
|
|
47
|
+
/**
|
|
48
|
+
* Include mutations matching this predicate function
|
|
49
|
+
*/
|
|
50
|
+
predicate?: (mutation: Mutation<any, any, any>) => boolean
|
|
51
|
+
/**
|
|
52
|
+
* Include mutations matching this mutation key
|
|
53
|
+
*/
|
|
54
|
+
mutationKey?: MutationKey
|
|
55
|
+
/**
|
|
56
|
+
* Include or exclude fetching mutations
|
|
57
|
+
*/
|
|
58
|
+
fetching?: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export type DataUpdateFunction<TInput, TOutput> = (input: TInput) => TOutput
|
|
62
|
+
|
|
63
|
+
export type Updater<TInput, TOutput> =
|
|
64
|
+
| TOutput
|
|
65
|
+
| DataUpdateFunction<TInput, TOutput>
|
|
66
|
+
|
|
67
|
+
export type QueryTypeFilter = 'all' | 'active' | 'inactive'
|
|
68
|
+
|
|
69
|
+
// UTILS
|
|
70
|
+
|
|
71
|
+
export const isServer = typeof window === 'undefined'
|
|
72
|
+
|
|
73
|
+
export function noop(): undefined {
|
|
74
|
+
return undefined
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function functionalUpdate<TInput, TOutput>(
|
|
78
|
+
updater: Updater<TInput, TOutput>,
|
|
79
|
+
input: TInput,
|
|
80
|
+
): TOutput {
|
|
81
|
+
return typeof updater === 'function'
|
|
82
|
+
? (updater as DataUpdateFunction<TInput, TOutput>)(input)
|
|
83
|
+
: updater
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function isValidTimeout(value: unknown): value is number {
|
|
87
|
+
return typeof value === 'number' && value >= 0 && value !== Infinity
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function difference<T>(array1: T[], array2: T[]): T[] {
|
|
91
|
+
return array1.filter((x) => array2.indexOf(x) === -1)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function replaceAt<T>(array: T[], index: number, value: T): T[] {
|
|
95
|
+
const copy = array.slice(0)
|
|
96
|
+
copy[index] = value
|
|
97
|
+
return copy
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function timeUntilStale(updatedAt: number, staleTime?: number): number {
|
|
101
|
+
return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function parseQueryArgs<
|
|
105
|
+
TOptions extends QueryOptions<any, any, any, TQueryKey>,
|
|
106
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
107
|
+
>(
|
|
108
|
+
arg1: TQueryKey | TOptions,
|
|
109
|
+
arg2?: QueryFunction<any, TQueryKey> | TOptions,
|
|
110
|
+
arg3?: TOptions,
|
|
111
|
+
): TOptions {
|
|
112
|
+
if (!isQueryKey(arg1)) {
|
|
113
|
+
return arg1 as TOptions
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (typeof arg2 === 'function') {
|
|
117
|
+
return { ...arg3, queryKey: arg1, queryFn: arg2 } as TOptions
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return { ...arg2, queryKey: arg1 } as TOptions
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function parseMutationArgs<
|
|
124
|
+
TOptions extends MutationOptions<any, any, any, any>,
|
|
125
|
+
>(
|
|
126
|
+
arg1: MutationKey | MutationFunction<any, any> | TOptions,
|
|
127
|
+
arg2?: MutationFunction<any, any> | TOptions,
|
|
128
|
+
arg3?: TOptions,
|
|
129
|
+
): TOptions {
|
|
130
|
+
if (isQueryKey(arg1)) {
|
|
131
|
+
if (typeof arg2 === 'function') {
|
|
132
|
+
return { ...arg3, mutationKey: arg1, mutationFn: arg2 } as TOptions
|
|
133
|
+
}
|
|
134
|
+
return { ...arg2, mutationKey: arg1 } as TOptions
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (typeof arg1 === 'function') {
|
|
138
|
+
return { ...arg2, mutationFn: arg1 } as TOptions
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return { ...arg1 } as TOptions
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function parseFilterArgs<
|
|
145
|
+
TFilters extends QueryFilters,
|
|
146
|
+
TOptions = unknown,
|
|
147
|
+
>(
|
|
148
|
+
arg1?: QueryKey | TFilters,
|
|
149
|
+
arg2?: TFilters | TOptions,
|
|
150
|
+
arg3?: TOptions,
|
|
151
|
+
): [TFilters, TOptions | undefined] {
|
|
152
|
+
return (
|
|
153
|
+
isQueryKey(arg1) ? [{ ...arg2, queryKey: arg1 }, arg3] : [arg1 || {}, arg2]
|
|
154
|
+
) as [TFilters, TOptions]
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export function parseMutationFilterArgs<
|
|
158
|
+
TFilters extends MutationFilters,
|
|
159
|
+
TOptions = unknown,
|
|
160
|
+
>(
|
|
161
|
+
arg1?: QueryKey | TFilters,
|
|
162
|
+
arg2?: TFilters | TOptions,
|
|
163
|
+
arg3?: TOptions,
|
|
164
|
+
): [TFilters, TOptions | undefined] {
|
|
165
|
+
return (
|
|
166
|
+
isQueryKey(arg1)
|
|
167
|
+
? [{ ...arg2, mutationKey: arg1 }, arg3]
|
|
168
|
+
: [arg1 || {}, arg2]
|
|
169
|
+
) as [TFilters, TOptions]
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function matchQuery(
|
|
173
|
+
filters: QueryFilters,
|
|
174
|
+
query: Query<any, any, any, any>,
|
|
175
|
+
): boolean {
|
|
176
|
+
const {
|
|
177
|
+
type = 'all',
|
|
178
|
+
exact,
|
|
179
|
+
fetchStatus,
|
|
180
|
+
predicate,
|
|
181
|
+
queryKey,
|
|
182
|
+
stale,
|
|
183
|
+
} = filters
|
|
184
|
+
|
|
185
|
+
if (isQueryKey(queryKey)) {
|
|
186
|
+
if (exact) {
|
|
187
|
+
if (query.queryHash !== hashQueryKeyByOptions(queryKey, query.options)) {
|
|
188
|
+
return false
|
|
189
|
+
}
|
|
190
|
+
} else if (!partialMatchKey(query.queryKey, queryKey)) {
|
|
191
|
+
return false
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (type !== 'all') {
|
|
196
|
+
const isActive = query.isActive()
|
|
197
|
+
if (type === 'active' && !isActive) {
|
|
198
|
+
return false
|
|
199
|
+
}
|
|
200
|
+
if (type === 'inactive' && isActive) {
|
|
201
|
+
return false
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (typeof stale === 'boolean' && query.isStale() !== stale) {
|
|
206
|
+
return false
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (
|
|
210
|
+
typeof fetchStatus !== 'undefined' &&
|
|
211
|
+
fetchStatus !== query.state.fetchStatus
|
|
212
|
+
) {
|
|
213
|
+
return false
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (predicate && !predicate(query)) {
|
|
217
|
+
return false
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return true
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function matchMutation(
|
|
224
|
+
filters: MutationFilters,
|
|
225
|
+
mutation: Mutation<any, any>,
|
|
226
|
+
): boolean {
|
|
227
|
+
const { exact, fetching, predicate, mutationKey } = filters
|
|
228
|
+
if (isQueryKey(mutationKey)) {
|
|
229
|
+
if (!mutation.options.mutationKey) {
|
|
230
|
+
return false
|
|
231
|
+
}
|
|
232
|
+
if (exact) {
|
|
233
|
+
if (
|
|
234
|
+
hashQueryKey(mutation.options.mutationKey) !== hashQueryKey(mutationKey)
|
|
235
|
+
) {
|
|
236
|
+
return false
|
|
237
|
+
}
|
|
238
|
+
} else if (!partialMatchKey(mutation.options.mutationKey, mutationKey)) {
|
|
239
|
+
return false
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (
|
|
244
|
+
typeof fetching === 'boolean' &&
|
|
245
|
+
(mutation.state.status === 'loading') !== fetching
|
|
246
|
+
) {
|
|
247
|
+
return false
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (predicate && !predicate(mutation)) {
|
|
251
|
+
return false
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return true
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function hashQueryKeyByOptions<TQueryKey extends QueryKey = QueryKey>(
|
|
258
|
+
queryKey: TQueryKey,
|
|
259
|
+
options?: QueryOptions<any, any, any, TQueryKey>,
|
|
260
|
+
): string {
|
|
261
|
+
const hashFn = options?.queryKeyHashFn || hashQueryKey
|
|
262
|
+
return hashFn(queryKey)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Default query keys hash function.
|
|
267
|
+
* Hashes the value into a stable hash.
|
|
268
|
+
*/
|
|
269
|
+
export function hashQueryKey(queryKey: QueryKey): string {
|
|
270
|
+
return JSON.stringify(queryKey, (_, val) =>
|
|
271
|
+
isPlainObject(val)
|
|
272
|
+
? Object.keys(val)
|
|
273
|
+
.sort()
|
|
274
|
+
.reduce((result, key) => {
|
|
275
|
+
result[key] = val[key]
|
|
276
|
+
return result
|
|
277
|
+
}, {} as any)
|
|
278
|
+
: val,
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Checks if key `b` partially matches with key `a`.
|
|
284
|
+
*/
|
|
285
|
+
export function partialMatchKey(a: QueryKey, b: QueryKey): boolean {
|
|
286
|
+
return partialDeepEqual(a, b)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Checks if `b` partially matches with `a`.
|
|
291
|
+
*/
|
|
292
|
+
export function partialDeepEqual(a: any, b: any): boolean {
|
|
293
|
+
if (a === b) {
|
|
294
|
+
return true
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (typeof a !== typeof b) {
|
|
298
|
+
return false
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (a && b && typeof a === 'object' && typeof b === 'object') {
|
|
302
|
+
return !Object.keys(b).some((key) => !partialDeepEqual(a[key], b[key]))
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return false
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* This function returns `a` if `b` is deeply equal.
|
|
310
|
+
* If not, it will replace any deeply equal children of `b` with those of `a`.
|
|
311
|
+
* This can be used for structural sharing between JSON values for example.
|
|
312
|
+
*/
|
|
313
|
+
export function replaceEqualDeep<T>(a: unknown, b: T): T
|
|
314
|
+
export function replaceEqualDeep(a: any, b: any): any {
|
|
315
|
+
if (a === b) {
|
|
316
|
+
return a
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const array = isPlainArray(a) && isPlainArray(b)
|
|
320
|
+
|
|
321
|
+
if (array || (isPlainObject(a) && isPlainObject(b))) {
|
|
322
|
+
const aSize = array ? a.length : Object.keys(a).length
|
|
323
|
+
const bItems = array ? b : Object.keys(b)
|
|
324
|
+
const bSize = bItems.length
|
|
325
|
+
const copy: any = array ? [] : {}
|
|
326
|
+
|
|
327
|
+
let equalItems = 0
|
|
328
|
+
|
|
329
|
+
for (let i = 0; i < bSize; i++) {
|
|
330
|
+
const key = array ? i : bItems[i]
|
|
331
|
+
copy[key] = replaceEqualDeep(a[key], b[key])
|
|
332
|
+
if (copy[key] === a[key]) {
|
|
333
|
+
equalItems++
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
return aSize === bSize && equalItems === aSize ? a : copy
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return b
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Shallow compare objects. Only works with objects that always have the same properties.
|
|
345
|
+
*/
|
|
346
|
+
export function shallowEqualObjects<T>(a: T, b: T): boolean {
|
|
347
|
+
if ((a && !b) || (b && !a)) {
|
|
348
|
+
return false
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
for (const key in a) {
|
|
352
|
+
if (a[key] !== b[key]) {
|
|
353
|
+
return false
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return true
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export function isPlainArray(value: unknown) {
|
|
361
|
+
return Array.isArray(value) && value.length === Object.keys(value).length
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// Copied from: https://github.com/jonschlinkert/is-plain-object
|
|
365
|
+
export function isPlainObject(o: any): o is Object {
|
|
366
|
+
if (!hasObjectPrototype(o)) {
|
|
367
|
+
return false
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// If has modified constructor
|
|
371
|
+
const ctor = o.constructor
|
|
372
|
+
if (typeof ctor === 'undefined') {
|
|
373
|
+
return true
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// If has modified prototype
|
|
377
|
+
const prot = ctor.prototype
|
|
378
|
+
if (!hasObjectPrototype(prot)) {
|
|
379
|
+
return false
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
// If constructor does not have an Object-specific method
|
|
383
|
+
if (!prot.hasOwnProperty('isPrototypeOf')) {
|
|
384
|
+
return false
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Most likely a plain Object
|
|
388
|
+
return true
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function hasObjectPrototype(o: any): boolean {
|
|
392
|
+
return Object.prototype.toString.call(o) === '[object Object]'
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
export function isQueryKey(value: unknown): value is QueryKey {
|
|
396
|
+
return Array.isArray(value)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function isError(value: any): value is Error {
|
|
400
|
+
return value instanceof Error
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export function sleep(timeout: number): Promise<void> {
|
|
404
|
+
return new Promise((resolve) => {
|
|
405
|
+
setTimeout(resolve, timeout)
|
|
406
|
+
})
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Schedules a microtask.
|
|
411
|
+
* This can be useful to schedule state updates after rendering.
|
|
412
|
+
*/
|
|
413
|
+
export function scheduleMicrotask(callback: () => void) {
|
|
414
|
+
sleep(0).then(callback)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
export function getAbortController(): AbortController | undefined {
|
|
418
|
+
if (typeof AbortController === 'function') {
|
|
419
|
+
return new AbortController()
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export function replaceData<
|
|
424
|
+
TData,
|
|
425
|
+
TOptions extends QueryOptions<any, any, any, any>,
|
|
426
|
+
>(prevData: TData | undefined, data: TData, options: TOptions): TData {
|
|
427
|
+
// Use prev data if an isDataEqual function is defined and returns `true`
|
|
428
|
+
if (options.isDataEqual?.(prevData, data)) {
|
|
429
|
+
return prevData as TData
|
|
430
|
+
} else if (options.structuralSharing !== false) {
|
|
431
|
+
// Structurally share data between prev and new data if needed
|
|
432
|
+
return replaceEqualDeep(prevData, data)
|
|
433
|
+
}
|
|
434
|
+
return data
|
|
435
|
+
}
|