@tanstack/query-core 5.27.5 → 5.28.2
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/legacy/hydration.d.cts +1 -1
- package/build/legacy/hydration.d.ts +1 -1
- package/build/legacy/index.d.cts +1 -1
- package/build/legacy/index.d.ts +1 -1
- package/build/legacy/infiniteQueryBehavior.d.cts +1 -1
- package/build/legacy/infiniteQueryBehavior.d.ts +1 -1
- package/build/legacy/infiniteQueryObserver.d.cts +1 -1
- package/build/legacy/infiniteQueryObserver.d.ts +1 -1
- package/build/legacy/mutation.d.cts +1 -1
- package/build/legacy/mutation.d.ts +1 -1
- package/build/legacy/mutationCache.d.cts +1 -1
- package/build/legacy/mutationCache.d.ts +1 -1
- package/build/legacy/mutationObserver.cjs +2 -2
- package/build/legacy/mutationObserver.cjs.map +1 -1
- package/build/legacy/mutationObserver.d.cts +1 -1
- package/build/legacy/mutationObserver.d.ts +1 -1
- package/build/legacy/mutationObserver.js +2 -2
- package/build/legacy/mutationObserver.js.map +1 -1
- package/build/legacy/queriesObserver.d.cts +1 -1
- package/build/legacy/queriesObserver.d.ts +1 -1
- package/build/legacy/query.d.cts +1 -1
- package/build/legacy/query.d.ts +1 -1
- package/build/legacy/queryCache.d.cts +1 -1
- package/build/legacy/queryCache.d.ts +1 -1
- package/build/legacy/{queryClient-WUwa1bEQ.d.ts → queryClient-UWB6EkqM.d.ts} +5 -2
- package/build/legacy/{queryClient-8vXd-6hw.d.cts → queryClient-WxLAyIG_.d.cts} +5 -2
- package/build/legacy/queryClient.cjs +10 -1
- package/build/legacy/queryClient.cjs.map +1 -1
- package/build/legacy/queryClient.d.cts +1 -1
- package/build/legacy/queryClient.d.ts +1 -1
- package/build/legacy/queryClient.js +10 -1
- package/build/legacy/queryClient.js.map +1 -1
- package/build/legacy/queryObserver.d.cts +1 -1
- package/build/legacy/queryObserver.d.ts +1 -1
- package/build/legacy/retryer.d.cts +1 -1
- package/build/legacy/retryer.d.ts +1 -1
- package/build/legacy/types.cjs.map +1 -1
- package/build/legacy/types.d.cts +1 -1
- package/build/legacy/types.d.ts +1 -1
- package/build/legacy/utils.d.cts +1 -1
- package/build/legacy/utils.d.ts +1 -1
- package/build/modern/hydration.d.cts +1 -1
- package/build/modern/hydration.d.ts +1 -1
- package/build/modern/index.d.cts +1 -1
- package/build/modern/index.d.ts +1 -1
- package/build/modern/infiniteQueryBehavior.d.cts +1 -1
- package/build/modern/infiniteQueryBehavior.d.ts +1 -1
- package/build/modern/infiniteQueryObserver.d.cts +1 -1
- package/build/modern/infiniteQueryObserver.d.ts +1 -1
- package/build/modern/mutation.d.cts +1 -1
- package/build/modern/mutation.d.ts +1 -1
- package/build/modern/mutationCache.d.cts +1 -1
- package/build/modern/mutationCache.d.ts +1 -1
- package/build/modern/mutationObserver.cjs +2 -2
- package/build/modern/mutationObserver.cjs.map +1 -1
- package/build/modern/mutationObserver.d.cts +1 -1
- package/build/modern/mutationObserver.d.ts +1 -1
- package/build/modern/mutationObserver.js +2 -2
- package/build/modern/mutationObserver.js.map +1 -1
- package/build/modern/queriesObserver.d.cts +1 -1
- package/build/modern/queriesObserver.d.ts +1 -1
- package/build/modern/query.d.cts +1 -1
- package/build/modern/query.d.ts +1 -1
- package/build/modern/queryCache.d.cts +1 -1
- package/build/modern/queryCache.d.ts +1 -1
- package/build/modern/{queryClient-WUwa1bEQ.d.ts → queryClient-UWB6EkqM.d.ts} +5 -2
- package/build/modern/{queryClient-8vXd-6hw.d.cts → queryClient-WxLAyIG_.d.cts} +5 -2
- package/build/modern/queryClient.cjs +10 -1
- package/build/modern/queryClient.cjs.map +1 -1
- package/build/modern/queryClient.d.cts +1 -1
- package/build/modern/queryClient.d.ts +1 -1
- package/build/modern/queryClient.js +10 -1
- package/build/modern/queryClient.js.map +1 -1
- package/build/modern/queryObserver.d.cts +1 -1
- package/build/modern/queryObserver.d.ts +1 -1
- package/build/modern/retryer.d.cts +1 -1
- package/build/modern/retryer.d.ts +1 -1
- package/build/modern/types.cjs.map +1 -1
- package/build/modern/types.d.cts +1 -1
- package/build/modern/types.d.ts +1 -1
- package/build/modern/utils.d.cts +1 -1
- package/build/modern/utils.d.ts +1 -1
- package/package.json +1 -1
- package/src/mutationObserver.ts +2 -2
- package/src/queryClient.ts +16 -4
- package/src/tests/mutationObserver.test.tsx +154 -0
- package/src/tests/queryClient.test.tsx +27 -0
- package/src/types.ts +16 -0
package/src/mutationObserver.ts
CHANGED
|
@@ -73,8 +73,8 @@ export class MutationObserver<
|
|
|
73
73
|
hashKey(prevOptions.mutationKey) !== hashKey(this.options.mutationKey)
|
|
74
74
|
) {
|
|
75
75
|
this.reset()
|
|
76
|
-
} else {
|
|
77
|
-
this.#currentMutation
|
|
76
|
+
} else if (this.#currentMutation?.state.status === 'pending') {
|
|
77
|
+
this.#currentMutation.setOptions(this.options)
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
package/src/queryClient.ts
CHANGED
|
@@ -19,6 +19,7 @@ import type {
|
|
|
19
19
|
DefaultError,
|
|
20
20
|
DefaultOptions,
|
|
21
21
|
DefaultedQueryObserverOptions,
|
|
22
|
+
EnsureQueryDataOptions,
|
|
22
23
|
FetchInfiniteQueryOptions,
|
|
23
24
|
FetchQueryOptions,
|
|
24
25
|
InfiniteData,
|
|
@@ -130,13 +131,24 @@ export class QueryClient {
|
|
|
130
131
|
TData = TQueryFnData,
|
|
131
132
|
TQueryKey extends QueryKey = QueryKey,
|
|
132
133
|
>(
|
|
133
|
-
options:
|
|
134
|
+
options: EnsureQueryDataOptions<TQueryFnData, TError, TData, TQueryKey>,
|
|
134
135
|
): Promise<TData> {
|
|
135
136
|
const cachedData = this.getQueryData<TData>(options.queryKey)
|
|
136
137
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
138
|
+
if (cachedData === undefined) return this.fetchQuery(options)
|
|
139
|
+
else {
|
|
140
|
+
const defaultedOptions = this.defaultQueryOptions(options)
|
|
141
|
+
const query = this.#queryCache.build(this, defaultedOptions)
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
options.revalidateIfStale &&
|
|
145
|
+
query.isStaleByTime(defaultedOptions.staleTime)
|
|
146
|
+
) {
|
|
147
|
+
void this.prefetchQuery(defaultedOptions)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return Promise.resolve(cachedData)
|
|
151
|
+
}
|
|
140
152
|
}
|
|
141
153
|
|
|
142
154
|
getQueriesData<TQueryFnData = unknown>(
|
|
@@ -169,4 +169,158 @@ describe('mutationObserver', () => {
|
|
|
169
169
|
|
|
170
170
|
unsubscribe()
|
|
171
171
|
})
|
|
172
|
+
|
|
173
|
+
test('changing mutation meta should not affect successful mutations', async () => {
|
|
174
|
+
const mutationObserver = new MutationObserver(queryClient, {
|
|
175
|
+
meta: { a: 1 },
|
|
176
|
+
mutationFn: async (text: string) => {
|
|
177
|
+
await sleep(5)
|
|
178
|
+
return text
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
const subscriptionHandler = vi.fn()
|
|
183
|
+
|
|
184
|
+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
|
|
185
|
+
|
|
186
|
+
await mutationObserver.mutate('input')
|
|
187
|
+
|
|
188
|
+
expect(queryClient.getMutationCache().find({})).toMatchObject({
|
|
189
|
+
options: { meta: { a: 1 } },
|
|
190
|
+
state: {
|
|
191
|
+
status: 'success',
|
|
192
|
+
data: 'input',
|
|
193
|
+
},
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
mutationObserver.setOptions({
|
|
197
|
+
meta: { a: 2 },
|
|
198
|
+
})
|
|
199
|
+
|
|
200
|
+
expect(queryClient.getMutationCache().find({})).toMatchObject({
|
|
201
|
+
options: { meta: { a: 1 } },
|
|
202
|
+
state: {
|
|
203
|
+
status: 'success',
|
|
204
|
+
data: 'input',
|
|
205
|
+
},
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
unsubscribe()
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
test('mutation cache should have different meta when updated between mutations', async () => {
|
|
212
|
+
const mutationFn = async (text: string) => {
|
|
213
|
+
await sleep(5)
|
|
214
|
+
return text
|
|
215
|
+
}
|
|
216
|
+
const mutationObserver = new MutationObserver(queryClient, {
|
|
217
|
+
meta: { a: 1 },
|
|
218
|
+
mutationFn,
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const subscriptionHandler = vi.fn()
|
|
222
|
+
|
|
223
|
+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
|
|
224
|
+
|
|
225
|
+
await mutationObserver.mutate('input')
|
|
226
|
+
|
|
227
|
+
mutationObserver.setOptions({
|
|
228
|
+
meta: { a: 2 },
|
|
229
|
+
mutationFn,
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
await mutationObserver.mutate('input')
|
|
233
|
+
|
|
234
|
+
const mutations = queryClient.getMutationCache().findAll()
|
|
235
|
+
expect(mutations[0]).toMatchObject({
|
|
236
|
+
options: { meta: { a: 1 } },
|
|
237
|
+
state: {
|
|
238
|
+
status: 'success',
|
|
239
|
+
data: 'input',
|
|
240
|
+
},
|
|
241
|
+
})
|
|
242
|
+
expect(mutations[1]).toMatchObject({
|
|
243
|
+
options: { meta: { a: 2 } },
|
|
244
|
+
state: {
|
|
245
|
+
status: 'success',
|
|
246
|
+
data: 'input',
|
|
247
|
+
},
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
unsubscribe()
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
test('changing mutation meta should not affect rejected mutations', async () => {
|
|
254
|
+
const mutationObserver = new MutationObserver(queryClient, {
|
|
255
|
+
meta: { a: 1 },
|
|
256
|
+
mutationFn: async (_: string) => {
|
|
257
|
+
await sleep(5)
|
|
258
|
+
return Promise.reject(new Error('err'))
|
|
259
|
+
},
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
const subscriptionHandler = vi.fn()
|
|
263
|
+
|
|
264
|
+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
|
|
265
|
+
|
|
266
|
+
await mutationObserver.mutate('input').catch(() => undefined)
|
|
267
|
+
|
|
268
|
+
expect(queryClient.getMutationCache().find({})).toMatchObject({
|
|
269
|
+
options: { meta: { a: 1 } },
|
|
270
|
+
state: {
|
|
271
|
+
status: 'error',
|
|
272
|
+
},
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
mutationObserver.setOptions({
|
|
276
|
+
meta: { a: 2 },
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
expect(queryClient.getMutationCache().find({})).toMatchObject({
|
|
280
|
+
options: { meta: { a: 1 } },
|
|
281
|
+
state: {
|
|
282
|
+
status: 'error',
|
|
283
|
+
},
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
unsubscribe()
|
|
287
|
+
})
|
|
288
|
+
|
|
289
|
+
test('changing mutation meta should affect pending mutations', async () => {
|
|
290
|
+
const mutationObserver = new MutationObserver(queryClient, {
|
|
291
|
+
meta: { a: 1 },
|
|
292
|
+
mutationFn: async (text: string) => {
|
|
293
|
+
await sleep(20)
|
|
294
|
+
return text
|
|
295
|
+
},
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
const subscriptionHandler = vi.fn()
|
|
299
|
+
|
|
300
|
+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
|
|
301
|
+
|
|
302
|
+
mutationObserver.mutate('input')
|
|
303
|
+
|
|
304
|
+
await sleep(0)
|
|
305
|
+
|
|
306
|
+
expect(queryClient.getMutationCache().find({})).toMatchObject({
|
|
307
|
+
options: { meta: { a: 1 } },
|
|
308
|
+
state: {
|
|
309
|
+
status: 'pending',
|
|
310
|
+
},
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
mutationObserver.setOptions({
|
|
314
|
+
meta: { a: 2 },
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
expect(queryClient.getMutationCache().find({})).toMatchObject({
|
|
318
|
+
options: { meta: { a: 2 } },
|
|
319
|
+
state: {
|
|
320
|
+
status: 'pending',
|
|
321
|
+
},
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
unsubscribe()
|
|
325
|
+
})
|
|
172
326
|
})
|
|
@@ -450,6 +450,33 @@ describe('queryClient', () => {
|
|
|
450
450
|
queryClient.ensureQueryData({ queryKey: [key], queryFn }),
|
|
451
451
|
).resolves.toEqual('data')
|
|
452
452
|
})
|
|
453
|
+
|
|
454
|
+
test('should return the cached query data if the query is found and preFetchQuery in the background when revalidateIfStale is set', async () => {
|
|
455
|
+
const TIMEOUT = 10
|
|
456
|
+
const key = queryKey()
|
|
457
|
+
queryClient.setQueryData([key, 'id'], 'old')
|
|
458
|
+
|
|
459
|
+
const queryFn = () =>
|
|
460
|
+
new Promise((resolve) => {
|
|
461
|
+
setTimeout(() => resolve('new'), TIMEOUT)
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
await expect(
|
|
465
|
+
queryClient.ensureQueryData({
|
|
466
|
+
queryKey: [key, 'id'],
|
|
467
|
+
queryFn,
|
|
468
|
+
revalidateIfStale: true,
|
|
469
|
+
}),
|
|
470
|
+
).resolves.toEqual('old')
|
|
471
|
+
await sleep(TIMEOUT + 10)
|
|
472
|
+
await expect(
|
|
473
|
+
queryClient.ensureQueryData({
|
|
474
|
+
queryKey: [key, 'id'],
|
|
475
|
+
queryFn,
|
|
476
|
+
revalidateIfStale: true,
|
|
477
|
+
}),
|
|
478
|
+
).resolves.toEqual('new')
|
|
479
|
+
})
|
|
453
480
|
})
|
|
454
481
|
|
|
455
482
|
describe('getQueriesData', () => {
|
package/src/types.ts
CHANGED
|
@@ -407,6 +407,22 @@ export interface FetchQueryOptions<
|
|
|
407
407
|
staleTime?: number
|
|
408
408
|
}
|
|
409
409
|
|
|
410
|
+
export interface EnsureQueryDataOptions<
|
|
411
|
+
TQueryFnData = unknown,
|
|
412
|
+
TError = DefaultError,
|
|
413
|
+
TData = TQueryFnData,
|
|
414
|
+
TQueryKey extends QueryKey = QueryKey,
|
|
415
|
+
TPageParam = never,
|
|
416
|
+
> extends FetchQueryOptions<
|
|
417
|
+
TQueryFnData,
|
|
418
|
+
TError,
|
|
419
|
+
TData,
|
|
420
|
+
TQueryKey,
|
|
421
|
+
TPageParam
|
|
422
|
+
> {
|
|
423
|
+
revalidateIfStale?: boolean
|
|
424
|
+
}
|
|
425
|
+
|
|
410
426
|
type FetchInfiniteQueryPages<TQueryFnData = unknown, TPageParam = unknown> =
|
|
411
427
|
| { pages?: never }
|
|
412
428
|
| {
|