@tanstack/react-query 5.0.0-alpha.19 → 5.0.0-alpha.21
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/lib/suspense.d.ts +1 -1
- package/build/lib/suspense.esm.js +1 -8
- package/build/lib/suspense.esm.js.map +1 -1
- package/build/lib/suspense.js +1 -8
- package/build/lib/suspense.js.map +1 -1
- package/build/lib/suspense.mjs +1 -8
- package/build/lib/suspense.mjs.map +1 -1
- package/build/lib/useBaseQuery.esm.js +0 -11
- package/build/lib/useBaseQuery.esm.js.map +1 -1
- package/build/lib/useBaseQuery.js +0 -11
- package/build/lib/useBaseQuery.js.map +1 -1
- package/build/lib/useBaseQuery.mjs +0 -11
- package/build/lib/useBaseQuery.mjs.map +1 -1
- package/build/lib/useQueries.esm.js +8 -7
- package/build/lib/useQueries.esm.js.map +1 -1
- package/build/lib/useQueries.js +8 -7
- package/build/lib/useQueries.js.map +1 -1
- package/build/lib/useQueries.mjs +8 -7
- package/build/lib/useQueries.mjs.map +1 -1
- package/build/umd/index.development.js +17 -48
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/QueryResetErrorBoundary.test.tsx +752 -620
- package/src/__tests__/suspense.test.tsx +0 -82
- package/src/__tests__/useInfiniteQuery.type.test.tsx +0 -27
- package/src/__tests__/useQueries.test.tsx +2 -73
- package/src/__tests__/useQuery.test.tsx +0 -332
- package/src/suspense.ts +3 -11
- package/src/useBaseQuery.ts +0 -19
- package/src/useQueries.ts +10 -11
|
@@ -190,88 +190,6 @@ describe("useQuery's in Suspense mode", () => {
|
|
|
190
190
|
expect(queryCache.find({ queryKey: key })?.getObserversCount()).toBe(0)
|
|
191
191
|
})
|
|
192
192
|
|
|
193
|
-
it('should call onSuccess on the first successful call', async () => {
|
|
194
|
-
const key = queryKey()
|
|
195
|
-
|
|
196
|
-
const successFn = vi.fn()
|
|
197
|
-
|
|
198
|
-
function Page() {
|
|
199
|
-
useQuery({
|
|
200
|
-
queryKey: [key],
|
|
201
|
-
queryFn: async () => {
|
|
202
|
-
await sleep(10)
|
|
203
|
-
return key
|
|
204
|
-
},
|
|
205
|
-
suspense: true,
|
|
206
|
-
select: () => 'selected',
|
|
207
|
-
onSuccess: successFn,
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
return <>rendered</>
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
const rendered = renderWithClient(
|
|
214
|
-
queryClient,
|
|
215
|
-
<React.Suspense fallback="loading">
|
|
216
|
-
<Page />
|
|
217
|
-
</React.Suspense>,
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
await waitFor(() => rendered.getByText('rendered'))
|
|
221
|
-
|
|
222
|
-
await waitFor(() => expect(successFn).toHaveBeenCalledTimes(1))
|
|
223
|
-
await waitFor(() => expect(successFn).toHaveBeenCalledWith('selected'))
|
|
224
|
-
})
|
|
225
|
-
|
|
226
|
-
it('should call every onSuccess handler within a suspense boundary', async () => {
|
|
227
|
-
const key = queryKey()
|
|
228
|
-
|
|
229
|
-
const successFn1 = vi.fn()
|
|
230
|
-
const successFn2 = vi.fn()
|
|
231
|
-
|
|
232
|
-
function FirstComponent() {
|
|
233
|
-
useQuery({
|
|
234
|
-
queryKey: key,
|
|
235
|
-
queryFn: () => {
|
|
236
|
-
sleep(10)
|
|
237
|
-
return 'data'
|
|
238
|
-
},
|
|
239
|
-
suspense: true,
|
|
240
|
-
onSuccess: successFn1,
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
return <span>first</span>
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
function SecondComponent() {
|
|
247
|
-
useQuery({
|
|
248
|
-
queryKey: key,
|
|
249
|
-
queryFn: () => {
|
|
250
|
-
sleep(10)
|
|
251
|
-
return 'data'
|
|
252
|
-
},
|
|
253
|
-
|
|
254
|
-
suspense: true,
|
|
255
|
-
onSuccess: successFn2,
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
return <span>second</span>
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
const rendered = renderWithClient(
|
|
262
|
-
queryClient,
|
|
263
|
-
<React.Suspense fallback="loading">
|
|
264
|
-
<FirstComponent />
|
|
265
|
-
<SecondComponent />
|
|
266
|
-
</React.Suspense>,
|
|
267
|
-
)
|
|
268
|
-
|
|
269
|
-
await waitFor(() => rendered.getByText('second'))
|
|
270
|
-
|
|
271
|
-
await waitFor(() => expect(successFn1).toHaveBeenCalledTimes(1))
|
|
272
|
-
await waitFor(() => expect(successFn2).toHaveBeenCalledTimes(1))
|
|
273
|
-
})
|
|
274
|
-
|
|
275
193
|
// https://github.com/tannerlinsley/react-query/issues/468
|
|
276
194
|
it('should reset error state if new component instances are mounted', async () => {
|
|
277
195
|
const consoleMock = vi
|
|
@@ -128,33 +128,6 @@ describe('select', () => {
|
|
|
128
128
|
return result
|
|
129
129
|
})
|
|
130
130
|
})
|
|
131
|
-
it('should pass transformed data to onSuccess', () => {
|
|
132
|
-
doNotExecute(() => {
|
|
133
|
-
const infiniteQuery = useInfiniteQuery({
|
|
134
|
-
queryKey: ['key'],
|
|
135
|
-
queryFn: ({ pageParam }) => {
|
|
136
|
-
return pageParam * 5
|
|
137
|
-
},
|
|
138
|
-
defaultPageParam: 1,
|
|
139
|
-
getNextPageParam: () => undefined,
|
|
140
|
-
select: (data) => {
|
|
141
|
-
return {
|
|
142
|
-
...data,
|
|
143
|
-
pages: data.pages.map((page) => page.toString()),
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
onSuccess: (data) => {
|
|
147
|
-
const result: Expect<Equal<InfiniteData<string>, typeof data>> = true
|
|
148
|
-
doNotExecute(() => result)
|
|
149
|
-
},
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
const result: Expect<
|
|
153
|
-
Equal<InfiniteData<string> | undefined, (typeof infiniteQuery)['data']>
|
|
154
|
-
> = true
|
|
155
|
-
return result
|
|
156
|
-
})
|
|
157
|
-
})
|
|
158
131
|
})
|
|
159
132
|
describe('getNextPageParam / getPreviousPageParam', () => {
|
|
160
133
|
it('should get typed params', () => {
|
|
@@ -144,10 +144,6 @@ describe('useQueries', () => {
|
|
|
144
144
|
expectTypeNotAny(a)
|
|
145
145
|
return a.toLowerCase()
|
|
146
146
|
},
|
|
147
|
-
onSuccess: (a) => {
|
|
148
|
-
expectType<string>(a)
|
|
149
|
-
expectTypeNotAny(a)
|
|
150
|
-
},
|
|
151
147
|
placeholderData: 'string',
|
|
152
148
|
// @ts-expect-error (initialData: string)
|
|
153
149
|
initialData: 123,
|
|
@@ -160,14 +156,6 @@ describe('useQueries', () => {
|
|
|
160
156
|
expectTypeNotAny(a)
|
|
161
157
|
return parseInt(a)
|
|
162
158
|
},
|
|
163
|
-
onSuccess: (a) => {
|
|
164
|
-
expectType<number>(a)
|
|
165
|
-
expectTypeNotAny(a)
|
|
166
|
-
},
|
|
167
|
-
onError: (e) => {
|
|
168
|
-
expectType<boolean>(e)
|
|
169
|
-
expectTypeNotAny(e)
|
|
170
|
-
},
|
|
171
159
|
placeholderData: 'string',
|
|
172
160
|
// @ts-expect-error (initialData: string)
|
|
173
161
|
initialData: 123,
|
|
@@ -304,10 +292,6 @@ describe('useQueries', () => {
|
|
|
304
292
|
expectTypeNotAny(a)
|
|
305
293
|
return a.toLowerCase()
|
|
306
294
|
},
|
|
307
|
-
onSuccess: (a) => {
|
|
308
|
-
expectType<string>(a)
|
|
309
|
-
expectTypeNotAny(a)
|
|
310
|
-
},
|
|
311
295
|
placeholderData: 'string',
|
|
312
296
|
// @ts-expect-error (initialData: string)
|
|
313
297
|
initialData: 123,
|
|
@@ -320,14 +304,6 @@ describe('useQueries', () => {
|
|
|
320
304
|
expectTypeNotAny(a)
|
|
321
305
|
return parseInt(a)
|
|
322
306
|
},
|
|
323
|
-
onSuccess: (a) => {
|
|
324
|
-
expectType<number>(a)
|
|
325
|
-
expectTypeNotAny(a)
|
|
326
|
-
},
|
|
327
|
-
onError: (e) => {
|
|
328
|
-
expectType<boolean>(e)
|
|
329
|
-
expectTypeNotAny(e)
|
|
330
|
-
},
|
|
331
307
|
placeholderData: 'string',
|
|
332
308
|
// @ts-expect-error (initialData: string)
|
|
333
309
|
initialData: 123,
|
|
@@ -423,60 +399,38 @@ describe('useQueries', () => {
|
|
|
423
399
|
],
|
|
424
400
|
})
|
|
425
401
|
|
|
426
|
-
// select
|
|
402
|
+
// select params are "indirectly" enforced
|
|
427
403
|
useQueries({
|
|
428
404
|
queries: [
|
|
429
405
|
// unfortunately TS will not suggest the type for you
|
|
430
406
|
{
|
|
431
407
|
queryKey: key1,
|
|
432
408
|
queryFn: () => 'string',
|
|
433
|
-
// @ts-expect-error (noImplicitAny)
|
|
434
|
-
onSuccess: (a) => null,
|
|
435
|
-
// @ts-expect-error (noImplicitAny)
|
|
436
|
-
onSettled: (a) => null,
|
|
437
409
|
},
|
|
438
410
|
// however you can add a type to the callback
|
|
439
411
|
{
|
|
440
412
|
queryKey: key2,
|
|
441
413
|
queryFn: () => 'string',
|
|
442
|
-
onSuccess: (a: string) => {
|
|
443
|
-
expectType<string>(a)
|
|
444
|
-
expectTypeNotAny(a)
|
|
445
|
-
},
|
|
446
|
-
onSettled: (a: string | undefined) => {
|
|
447
|
-
expectType<string | undefined>(a)
|
|
448
|
-
expectTypeNotAny(a)
|
|
449
|
-
},
|
|
450
414
|
},
|
|
451
415
|
// the type you do pass is enforced
|
|
452
416
|
{
|
|
453
417
|
queryKey: key3,
|
|
454
418
|
queryFn: () => 'string',
|
|
455
|
-
// @ts-expect-error (only accepts string)
|
|
456
|
-
onSuccess: (a: number) => null,
|
|
457
419
|
},
|
|
458
420
|
{
|
|
459
421
|
queryKey: key4,
|
|
460
422
|
queryFn: () => 'string',
|
|
461
423
|
select: (a: string) => parseInt(a),
|
|
462
|
-
// @ts-expect-error (select is defined => only accepts number)
|
|
463
|
-
onSuccess: (a: string) => null,
|
|
464
|
-
onSettled: (a: number | undefined) => {
|
|
465
|
-
expectType<number | undefined>(a)
|
|
466
|
-
expectTypeNotAny(a)
|
|
467
|
-
},
|
|
468
424
|
},
|
|
469
425
|
],
|
|
470
426
|
})
|
|
471
427
|
|
|
472
428
|
// callbacks are also indirectly enforced with Array.map
|
|
473
429
|
useQueries({
|
|
474
|
-
// @ts-expect-error (onSuccess only accepts string)
|
|
475
430
|
queries: Array(50).map((_, i) => ({
|
|
476
431
|
queryKey: ['key', i] as const,
|
|
477
432
|
queryFn: () => i + 10,
|
|
478
433
|
select: (data: number) => data.toString(),
|
|
479
|
-
onSuccess: (_data: number) => null,
|
|
480
434
|
})),
|
|
481
435
|
})
|
|
482
436
|
useQueries({
|
|
@@ -484,7 +438,6 @@ describe('useQueries', () => {
|
|
|
484
438
|
queryKey: ['key', i] as const,
|
|
485
439
|
queryFn: () => i + 10,
|
|
486
440
|
select: (data: number) => data.toString(),
|
|
487
|
-
onSuccess: (_data: string) => null,
|
|
488
441
|
})),
|
|
489
442
|
})
|
|
490
443
|
|
|
@@ -494,32 +447,15 @@ describe('useQueries', () => {
|
|
|
494
447
|
{
|
|
495
448
|
queryKey: key1,
|
|
496
449
|
queryFn: () => 'string',
|
|
497
|
-
// @ts-expect-error (noImplicitAny)
|
|
498
|
-
onSuccess: (a) => null,
|
|
499
|
-
// @ts-expect-error (noImplicitAny)
|
|
500
|
-
onSettled: (a) => null,
|
|
501
450
|
},
|
|
502
451
|
{
|
|
503
452
|
queryKey: key2,
|
|
504
453
|
queryFn: () => 'string',
|
|
505
|
-
onSuccess: (a: string) => {
|
|
506
|
-
expectType<string>(a)
|
|
507
|
-
expectTypeNotAny(a)
|
|
508
|
-
},
|
|
509
|
-
onSettled: (a: string | undefined) => {
|
|
510
|
-
expectType<string | undefined>(a)
|
|
511
|
-
expectTypeNotAny(a)
|
|
512
|
-
},
|
|
513
454
|
},
|
|
514
455
|
{
|
|
515
456
|
queryKey: key4,
|
|
516
457
|
queryFn: () => 'string',
|
|
517
458
|
select: (a: string) => parseInt(a),
|
|
518
|
-
onSuccess: (_a: number) => null,
|
|
519
|
-
onSettled: (a: number | undefined) => {
|
|
520
|
-
expectType<number | undefined>(a)
|
|
521
|
-
expectTypeNotAny(a)
|
|
522
|
-
},
|
|
523
459
|
},
|
|
524
460
|
],
|
|
525
461
|
})
|
|
@@ -533,12 +469,6 @@ describe('useQueries', () => {
|
|
|
533
469
|
{
|
|
534
470
|
queryKey: key1,
|
|
535
471
|
queryFn: () => Promise.resolve('string'),
|
|
536
|
-
onSuccess: (a: string) => {
|
|
537
|
-
expectType<string>(a)
|
|
538
|
-
expectTypeNotAny(a)
|
|
539
|
-
},
|
|
540
|
-
// @ts-expect-error (refuses to accept a Promise)
|
|
541
|
-
onSettled: (a: Promise<string>) => null,
|
|
542
472
|
},
|
|
543
473
|
],
|
|
544
474
|
})
|
|
@@ -645,11 +575,10 @@ describe('useQueries', () => {
|
|
|
645
575
|
queries: queries.map(
|
|
646
576
|
// no need to type the mapped query
|
|
647
577
|
(query) => {
|
|
648
|
-
const { queryFn: fn, queryKey: key
|
|
578
|
+
const { queryFn: fn, queryKey: key } = query
|
|
649
579
|
expectType<QueryFunction<TQueryFnData, TQueryKey> | undefined>(fn)
|
|
650
580
|
return {
|
|
651
581
|
queryKey: key,
|
|
652
|
-
onError: err,
|
|
653
582
|
queryFn: fn
|
|
654
583
|
? (ctx: QueryFunctionContext<TQueryKey>) => {
|
|
655
584
|
expectType<TQueryKey>(ctx.queryKey)
|
|
@@ -64,23 +64,17 @@ describe('useQuery', () => {
|
|
|
64
64
|
useQuery({
|
|
65
65
|
queryKey: [key],
|
|
66
66
|
queryFn: async () => true,
|
|
67
|
-
onSuccess: (data) => expectType<boolean>(data),
|
|
68
|
-
onSettled: (data) => expectType<boolean | undefined>(data),
|
|
69
67
|
})
|
|
70
68
|
|
|
71
69
|
// it should be possible to specify a union type as result type
|
|
72
70
|
const unionTypeSync = useQuery({
|
|
73
71
|
queryKey: key,
|
|
74
72
|
queryFn: () => (Math.random() > 0.5 ? 'a' : 'b'),
|
|
75
|
-
|
|
76
|
-
onSuccess: (data) => expectType<'a' | 'b'>(data),
|
|
77
73
|
})
|
|
78
74
|
expectType<'a' | 'b' | undefined>(unionTypeSync.data)
|
|
79
75
|
const unionTypeAsync = useQuery<'a' | 'b'>({
|
|
80
76
|
queryKey: key,
|
|
81
77
|
queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),
|
|
82
|
-
|
|
83
|
-
onSuccess: (data) => expectType<'a' | 'b'>(data),
|
|
84
78
|
})
|
|
85
79
|
expectType<'a' | 'b' | undefined>(unionTypeAsync.data)
|
|
86
80
|
|
|
@@ -450,255 +444,6 @@ describe('useQuery', () => {
|
|
|
450
444
|
})
|
|
451
445
|
})
|
|
452
446
|
|
|
453
|
-
it('should call onSuccess after a query has been fetched', async () => {
|
|
454
|
-
const key = queryKey()
|
|
455
|
-
const states: UseQueryResult<string>[] = []
|
|
456
|
-
const onSuccess = vi.fn()
|
|
457
|
-
|
|
458
|
-
function Page() {
|
|
459
|
-
const state = useQuery({
|
|
460
|
-
queryKey: key,
|
|
461
|
-
queryFn: async () => {
|
|
462
|
-
await sleep(10)
|
|
463
|
-
return 'data'
|
|
464
|
-
},
|
|
465
|
-
onSuccess,
|
|
466
|
-
})
|
|
467
|
-
states.push(state)
|
|
468
|
-
return <div>data: {state.data}</div>
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
472
|
-
|
|
473
|
-
await rendered.findByText('data: data')
|
|
474
|
-
expect(states.length).toBe(2)
|
|
475
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
476
|
-
expect(onSuccess).toHaveBeenCalledWith('data')
|
|
477
|
-
})
|
|
478
|
-
|
|
479
|
-
it('should call onSuccess after a query has been refetched', async () => {
|
|
480
|
-
const key = queryKey()
|
|
481
|
-
const states: UseQueryResult<string>[] = []
|
|
482
|
-
const onSuccess = vi.fn()
|
|
483
|
-
let count = 0
|
|
484
|
-
|
|
485
|
-
function Page() {
|
|
486
|
-
const state = useQuery({
|
|
487
|
-
queryKey: key,
|
|
488
|
-
queryFn: async () => {
|
|
489
|
-
count++
|
|
490
|
-
await sleep(10)
|
|
491
|
-
return 'data' + count
|
|
492
|
-
},
|
|
493
|
-
onSuccess,
|
|
494
|
-
})
|
|
495
|
-
|
|
496
|
-
states.push(state)
|
|
497
|
-
|
|
498
|
-
return (
|
|
499
|
-
<div>
|
|
500
|
-
<div>data: {state.data}</div>
|
|
501
|
-
<button onClick={() => state.refetch()}>refetch</button>
|
|
502
|
-
</div>
|
|
503
|
-
)
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
507
|
-
|
|
508
|
-
await rendered.findByText('data: data1')
|
|
509
|
-
fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
|
|
510
|
-
await rendered.findByText('data: data2')
|
|
511
|
-
|
|
512
|
-
expect(states.length).toBe(3) //pending, success, success after refetch
|
|
513
|
-
expect(count).toBe(2)
|
|
514
|
-
expect(onSuccess).toHaveBeenCalledTimes(2)
|
|
515
|
-
})
|
|
516
|
-
|
|
517
|
-
it('should call onSuccess after a disabled query has been fetched', async () => {
|
|
518
|
-
const key = queryKey()
|
|
519
|
-
const states: UseQueryResult<string>[] = []
|
|
520
|
-
const onSuccess = vi.fn()
|
|
521
|
-
|
|
522
|
-
function Page() {
|
|
523
|
-
const state = useQuery({
|
|
524
|
-
queryKey: key,
|
|
525
|
-
queryFn: () => 'data',
|
|
526
|
-
enabled: false,
|
|
527
|
-
onSuccess,
|
|
528
|
-
})
|
|
529
|
-
|
|
530
|
-
states.push(state)
|
|
531
|
-
|
|
532
|
-
return (
|
|
533
|
-
<div>
|
|
534
|
-
<div>isSuccess: {state.isSuccess ? 'true' : 'false'}</div>
|
|
535
|
-
<button onClick={() => state.refetch()}>refetch</button>
|
|
536
|
-
</div>
|
|
537
|
-
)
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
541
|
-
|
|
542
|
-
await waitFor(() => {
|
|
543
|
-
rendered.getByText('isSuccess: false')
|
|
544
|
-
})
|
|
545
|
-
|
|
546
|
-
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
547
|
-
|
|
548
|
-
await waitFor(() => {
|
|
549
|
-
rendered.getByText('isSuccess: true')
|
|
550
|
-
})
|
|
551
|
-
|
|
552
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
553
|
-
expect(onSuccess).toHaveBeenCalledWith('data')
|
|
554
|
-
})
|
|
555
|
-
|
|
556
|
-
it('should not call onSuccess if a component has unmounted', async () => {
|
|
557
|
-
const key = queryKey()
|
|
558
|
-
const states: UseQueryResult<string>[] = []
|
|
559
|
-
const onSuccess = vi.fn()
|
|
560
|
-
|
|
561
|
-
function Page() {
|
|
562
|
-
const [show, setShow] = React.useState(true)
|
|
563
|
-
|
|
564
|
-
React.useEffect(() => {
|
|
565
|
-
setShow(false)
|
|
566
|
-
}, [setShow])
|
|
567
|
-
|
|
568
|
-
return show ? <Component /> : null
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
function Component() {
|
|
572
|
-
const state = useQuery({
|
|
573
|
-
queryKey: key,
|
|
574
|
-
queryFn: async () => {
|
|
575
|
-
await sleep(10)
|
|
576
|
-
return 'data'
|
|
577
|
-
},
|
|
578
|
-
onSuccess,
|
|
579
|
-
})
|
|
580
|
-
states.push(state)
|
|
581
|
-
return null
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
renderWithClient(queryClient, <Page />)
|
|
585
|
-
|
|
586
|
-
await sleep(50)
|
|
587
|
-
expect(states.length).toBe(1)
|
|
588
|
-
expect(onSuccess).toHaveBeenCalledTimes(0)
|
|
589
|
-
})
|
|
590
|
-
|
|
591
|
-
it('should call onError after a query has been fetched with an error', async () => {
|
|
592
|
-
const key = queryKey()
|
|
593
|
-
const states: UseQueryResult<unknown>[] = []
|
|
594
|
-
const onError = vi.fn()
|
|
595
|
-
|
|
596
|
-
function Page() {
|
|
597
|
-
const state = useQuery<unknown>({
|
|
598
|
-
queryKey: key,
|
|
599
|
-
queryFn: () => Promise.reject(new Error('error')),
|
|
600
|
-
retry: false,
|
|
601
|
-
onError,
|
|
602
|
-
})
|
|
603
|
-
states.push(state)
|
|
604
|
-
return null
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
renderWithClient(queryClient, <Page />)
|
|
608
|
-
|
|
609
|
-
await sleep(10)
|
|
610
|
-
expect(states.length).toBe(2)
|
|
611
|
-
expect(onError).toHaveBeenCalledTimes(1)
|
|
612
|
-
expect(onError).toHaveBeenCalledWith(new Error('error'))
|
|
613
|
-
})
|
|
614
|
-
|
|
615
|
-
it('should not call onError when receiving a CancelledError', async () => {
|
|
616
|
-
const key = queryKey()
|
|
617
|
-
const onError = vi.fn()
|
|
618
|
-
|
|
619
|
-
function Page() {
|
|
620
|
-
const { status, fetchStatus } = useQuery({
|
|
621
|
-
queryKey: key,
|
|
622
|
-
queryFn: async () => {
|
|
623
|
-
await sleep(10)
|
|
624
|
-
return 23
|
|
625
|
-
},
|
|
626
|
-
|
|
627
|
-
onError,
|
|
628
|
-
})
|
|
629
|
-
return (
|
|
630
|
-
<span>
|
|
631
|
-
status: {status}, fetchStatus: {fetchStatus}
|
|
632
|
-
</span>
|
|
633
|
-
)
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
637
|
-
|
|
638
|
-
rendered.getByText('status: pending, fetchStatus: fetching')
|
|
639
|
-
|
|
640
|
-
await queryClient.cancelQueries({ queryKey: key })
|
|
641
|
-
// query cancellation will reset the query to it's initial state
|
|
642
|
-
await waitFor(() =>
|
|
643
|
-
rendered.getByText('status: pending, fetchStatus: idle'),
|
|
644
|
-
)
|
|
645
|
-
expect(onError).not.toHaveBeenCalled()
|
|
646
|
-
})
|
|
647
|
-
|
|
648
|
-
it('should call onSettled after a query has been fetched', async () => {
|
|
649
|
-
const key = queryKey()
|
|
650
|
-
const states: UseQueryResult<string>[] = []
|
|
651
|
-
const onSettled = vi.fn()
|
|
652
|
-
|
|
653
|
-
function Page() {
|
|
654
|
-
const state = useQuery({
|
|
655
|
-
queryKey: key,
|
|
656
|
-
queryFn: () => 'data',
|
|
657
|
-
onSettled,
|
|
658
|
-
})
|
|
659
|
-
states.push(state)
|
|
660
|
-
|
|
661
|
-
return <div>data: {state.data}</div>
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
665
|
-
|
|
666
|
-
await waitFor(() => {
|
|
667
|
-
rendered.getByText('data: data')
|
|
668
|
-
})
|
|
669
|
-
|
|
670
|
-
expect(states.length).toBe(2)
|
|
671
|
-
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
672
|
-
expect(onSettled).toHaveBeenCalledWith('data', null)
|
|
673
|
-
})
|
|
674
|
-
|
|
675
|
-
it('should call onSettled after a query has been fetched with an error', async () => {
|
|
676
|
-
const key = queryKey()
|
|
677
|
-
const onSettled = vi.fn()
|
|
678
|
-
const error = new Error('error')
|
|
679
|
-
|
|
680
|
-
function Page() {
|
|
681
|
-
const state = useQuery({
|
|
682
|
-
queryKey: key,
|
|
683
|
-
queryFn: async () => {
|
|
684
|
-
await sleep(10)
|
|
685
|
-
return Promise.reject(error)
|
|
686
|
-
},
|
|
687
|
-
retry: false,
|
|
688
|
-
onSettled,
|
|
689
|
-
})
|
|
690
|
-
return <div>status: {state.status}</div>
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
694
|
-
|
|
695
|
-
await waitFor(() => {
|
|
696
|
-
rendered.getByText('status: error')
|
|
697
|
-
})
|
|
698
|
-
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
699
|
-
expect(onSettled).toHaveBeenCalledWith(undefined, error)
|
|
700
|
-
})
|
|
701
|
-
|
|
702
447
|
it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {
|
|
703
448
|
const key = queryKey()
|
|
704
449
|
let fetchCount = 0
|
|
@@ -2587,53 +2332,6 @@ describe('useQuery', () => {
|
|
|
2587
2332
|
expect(renders).toBe(2)
|
|
2588
2333
|
})
|
|
2589
2334
|
|
|
2590
|
-
it('should batch re-renders including hook callbacks', async () => {
|
|
2591
|
-
const key = queryKey()
|
|
2592
|
-
|
|
2593
|
-
let renders = 0
|
|
2594
|
-
let callbackCount = 0
|
|
2595
|
-
|
|
2596
|
-
const queryFn = async () => {
|
|
2597
|
-
await sleep(10)
|
|
2598
|
-
return 'data'
|
|
2599
|
-
}
|
|
2600
|
-
|
|
2601
|
-
function Page() {
|
|
2602
|
-
const [count, setCount] = React.useState(0)
|
|
2603
|
-
useQuery({
|
|
2604
|
-
queryKey: key,
|
|
2605
|
-
queryFn,
|
|
2606
|
-
onSuccess: () => {
|
|
2607
|
-
setCount((x) => x + 1)
|
|
2608
|
-
},
|
|
2609
|
-
})
|
|
2610
|
-
useQuery({
|
|
2611
|
-
queryKey: key,
|
|
2612
|
-
queryFn,
|
|
2613
|
-
onSuccess: () => {
|
|
2614
|
-
setCount((x) => x + 1)
|
|
2615
|
-
},
|
|
2616
|
-
})
|
|
2617
|
-
|
|
2618
|
-
React.useEffect(() => {
|
|
2619
|
-
renders++
|
|
2620
|
-
callbackCount = count
|
|
2621
|
-
})
|
|
2622
|
-
|
|
2623
|
-
return <div>count: {count}</div>
|
|
2624
|
-
}
|
|
2625
|
-
|
|
2626
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
2627
|
-
|
|
2628
|
-
await waitFor(() => rendered.getByText('count: 2'))
|
|
2629
|
-
|
|
2630
|
-
// Should be 3 instead of 5
|
|
2631
|
-
expect(renders).toBe(3)
|
|
2632
|
-
|
|
2633
|
-
// Both callbacks should have been executed
|
|
2634
|
-
expect(callbackCount).toBe(2)
|
|
2635
|
-
})
|
|
2636
|
-
|
|
2637
2335
|
it('should render latest data even if react has discarded certain renders', async () => {
|
|
2638
2336
|
const key = queryKey()
|
|
2639
2337
|
|
|
@@ -6126,36 +5824,6 @@ describe('useQuery', () => {
|
|
|
6126
5824
|
})
|
|
6127
5825
|
})
|
|
6128
5826
|
|
|
6129
|
-
it('setQueryData - should not call onSuccess callback of active observers', async () => {
|
|
6130
|
-
const key = queryKey()
|
|
6131
|
-
const onSuccess = vi.fn()
|
|
6132
|
-
|
|
6133
|
-
function Page() {
|
|
6134
|
-
const state = useQuery({
|
|
6135
|
-
queryKey: key,
|
|
6136
|
-
queryFn: () => 'data',
|
|
6137
|
-
onSuccess,
|
|
6138
|
-
})
|
|
6139
|
-
return (
|
|
6140
|
-
<div>
|
|
6141
|
-
<div>data: {state.data}</div>
|
|
6142
|
-
<button onClick={() => queryClient.setQueryData(key, 'newData')}>
|
|
6143
|
-
setQueryData
|
|
6144
|
-
</button>
|
|
6145
|
-
</div>
|
|
6146
|
-
)
|
|
6147
|
-
}
|
|
6148
|
-
|
|
6149
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
6150
|
-
|
|
6151
|
-
await waitFor(() => rendered.getByText('data: data'))
|
|
6152
|
-
fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i }))
|
|
6153
|
-
await waitFor(() => rendered.getByText('data: newData'))
|
|
6154
|
-
|
|
6155
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
6156
|
-
expect(onSuccess).toHaveBeenCalledWith('data')
|
|
6157
|
-
})
|
|
6158
|
-
|
|
6159
5827
|
it('setQueryData - should respect updatedAt', async () => {
|
|
6160
5828
|
const key = queryKey()
|
|
6161
5829
|
|
package/src/suspense.ts
CHANGED
|
@@ -46,14 +46,6 @@ export const fetchOptimistic = <
|
|
|
46
46
|
observer: QueryObserver<TQueryFnData, TError, TData, TQueryData, TQueryKey>,
|
|
47
47
|
errorResetBoundary: QueryErrorResetBoundaryValue,
|
|
48
48
|
) =>
|
|
49
|
-
observer
|
|
50
|
-
.
|
|
51
|
-
|
|
52
|
-
defaultedOptions.onSuccess?.(data as TData)
|
|
53
|
-
defaultedOptions.onSettled?.(data, null)
|
|
54
|
-
})
|
|
55
|
-
.catch((error) => {
|
|
56
|
-
errorResetBoundary.clearReset()
|
|
57
|
-
defaultedOptions.onError?.(error)
|
|
58
|
-
defaultedOptions.onSettled?.(undefined, error)
|
|
59
|
-
})
|
|
49
|
+
observer.fetchOptimistic(defaultedOptions).catch(() => {
|
|
50
|
+
errorResetBoundary.clearReset()
|
|
51
|
+
})
|