@tanstack/react-query 5.0.0-alpha.2 → 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/HydrationBoundary.esm.js +1 -0
- package/build/lib/HydrationBoundary.esm.js.map +1 -1
- package/build/lib/HydrationBoundary.js +1 -0
- package/build/lib/HydrationBoundary.js.map +1 -1
- package/build/lib/HydrationBoundary.mjs +1 -0
- package/build/lib/HydrationBoundary.mjs.map +1 -1
- package/build/lib/QueryClientProvider.esm.js +1 -0
- package/build/lib/QueryClientProvider.esm.js.map +1 -1
- package/build/lib/QueryClientProvider.js +1 -0
- package/build/lib/QueryClientProvider.js.map +1 -1
- package/build/lib/QueryClientProvider.mjs +1 -0
- package/build/lib/QueryClientProvider.mjs.map +1 -1
- package/build/lib/QueryErrorResetBoundary.esm.js +1 -0
- package/build/lib/QueryErrorResetBoundary.esm.js.map +1 -1
- package/build/lib/QueryErrorResetBoundary.js +1 -0
- package/build/lib/QueryErrorResetBoundary.js.map +1 -1
- package/build/lib/QueryErrorResetBoundary.mjs +1 -0
- package/build/lib/QueryErrorResetBoundary.mjs.map +1 -1
- package/build/lib/__tests__/ssr.test.d.ts +0 -3
- package/build/lib/__tests__/utils.d.ts +2 -3
- package/build/lib/errorBoundaryUtils.esm.js +1 -0
- package/build/lib/errorBoundaryUtils.esm.js.map +1 -1
- package/build/lib/errorBoundaryUtils.js +1 -0
- package/build/lib/errorBoundaryUtils.js.map +1 -1
- package/build/lib/errorBoundaryUtils.mjs +1 -0
- package/build/lib/errorBoundaryUtils.mjs.map +1 -1
- package/build/lib/isRestoring.esm.js +1 -0
- package/build/lib/isRestoring.esm.js.map +1 -1
- package/build/lib/isRestoring.js +1 -0
- package/build/lib/isRestoring.js.map +1 -1
- package/build/lib/isRestoring.mjs +1 -0
- package/build/lib/isRestoring.mjs.map +1 -1
- package/build/lib/suspense.d.ts +1 -1
- package/build/lib/suspense.esm.js +2 -9
- package/build/lib/suspense.esm.js.map +1 -1
- package/build/lib/suspense.js +2 -9
- 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 +1 -11
- package/build/lib/useBaseQuery.esm.js.map +1 -1
- package/build/lib/useBaseQuery.js +1 -11
- package/build/lib/useBaseQuery.js.map +1 -1
- package/build/lib/useBaseQuery.mjs +1 -11
- package/build/lib/useBaseQuery.mjs.map +1 -1
- package/build/lib/useInfiniteQuery.esm.js +1 -0
- package/build/lib/useInfiniteQuery.esm.js.map +1 -1
- package/build/lib/useInfiniteQuery.js +1 -0
- package/build/lib/useInfiniteQuery.js.map +1 -1
- package/build/lib/useInfiniteQuery.mjs +1 -0
- package/build/lib/useInfiniteQuery.mjs.map +1 -1
- package/build/lib/useIsFetching.esm.js +1 -0
- package/build/lib/useIsFetching.esm.js.map +1 -1
- package/build/lib/useIsFetching.js +1 -0
- package/build/lib/useIsFetching.js.map +1 -1
- package/build/lib/useIsFetching.mjs +1 -0
- package/build/lib/useIsFetching.mjs.map +1 -1
- package/build/lib/useMutation.esm.js +1 -0
- package/build/lib/useMutation.esm.js.map +1 -1
- package/build/lib/useMutation.js +1 -0
- package/build/lib/useMutation.js.map +1 -1
- package/build/lib/useMutation.mjs +1 -0
- package/build/lib/useMutation.mjs.map +1 -1
- package/build/lib/useMutationState.d.ts +3 -3
- package/build/lib/useMutationState.esm.js +1 -0
- package/build/lib/useMutationState.esm.js.map +1 -1
- package/build/lib/useMutationState.js +1 -0
- package/build/lib/useMutationState.js.map +1 -1
- package/build/lib/useMutationState.mjs +1 -0
- package/build/lib/useMutationState.mjs.map +1 -1
- package/build/lib/useQueries.d.ts +2 -3
- package/build/lib/useQueries.esm.js +20 -16
- package/build/lib/useQueries.esm.js.map +1 -1
- package/build/lib/useQueries.js +20 -16
- package/build/lib/useQueries.js.map +1 -1
- package/build/lib/useQueries.mjs +11 -10
- package/build/lib/useQueries.mjs.map +1 -1
- package/build/lib/useQuery.esm.js +1 -0
- package/build/lib/useQuery.esm.js.map +1 -1
- package/build/lib/useQuery.js +1 -0
- package/build/lib/useQuery.js.map +1 -1
- package/build/lib/useQuery.mjs +1 -0
- package/build/lib/useQuery.mjs.map +1 -1
- package/build/umd/index.development.js +108 -138
- 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 +3 -3
- package/src/__tests__/HydrationBoundary.test.tsx +4 -3
- package/src/__tests__/QueryClientProvider.test.tsx +2 -1
- package/src/__tests__/QueryResetErrorBoundary.test.tsx +753 -620
- package/src/__tests__/ssr-hydration.test.tsx +11 -10
- package/src/__tests__/ssr.test.tsx +4 -7
- package/src/__tests__/suspense.test.tsx +11 -92
- package/src/__tests__/useInfiniteQuery.test.tsx +18 -16
- package/src/__tests__/useInfiniteQuery.type.test.tsx +94 -13
- package/src/__tests__/useMutation.test.tsx +21 -20
- package/src/__tests__/useMutationState.test.tsx +24 -58
- package/src/__tests__/useQueries.test.tsx +25 -154
- package/src/__tests__/useQuery.test.tsx +174 -359
- package/src/__tests__/utils.tsx +3 -2
- package/src/errorBoundaryUtils.ts +1 -0
- package/src/suspense.ts +3 -11
- package/src/useBaseQuery.ts +1 -19
- package/src/useInfiniteQuery.ts +1 -0
- package/src/useIsFetching.ts +1 -0
- package/src/useMutation.ts +1 -0
- package/src/useMutationState.ts +4 -3
- package/src/useQueries.ts +19 -18
- package/src/useQuery.ts +1 -0
|
@@ -21,6 +21,8 @@ import type {
|
|
|
21
21
|
} from '..'
|
|
22
22
|
import { QueryCache, useQuery, keepPreviousData } from '..'
|
|
23
23
|
import { ErrorBoundary } from 'react-error-boundary'
|
|
24
|
+
import { vi } from 'vitest'
|
|
25
|
+
import type { Mock } from 'vitest'
|
|
24
26
|
|
|
25
27
|
describe('useQuery', () => {
|
|
26
28
|
const queryCache = new QueryCache()
|
|
@@ -62,23 +64,17 @@ describe('useQuery', () => {
|
|
|
62
64
|
useQuery({
|
|
63
65
|
queryKey: [key],
|
|
64
66
|
queryFn: async () => true,
|
|
65
|
-
onSuccess: (data) => expectType<boolean>(data),
|
|
66
|
-
onSettled: (data) => expectType<boolean | undefined>(data),
|
|
67
67
|
})
|
|
68
68
|
|
|
69
69
|
// it should be possible to specify a union type as result type
|
|
70
70
|
const unionTypeSync = useQuery({
|
|
71
71
|
queryKey: key,
|
|
72
72
|
queryFn: () => (Math.random() > 0.5 ? 'a' : 'b'),
|
|
73
|
-
|
|
74
|
-
onSuccess: (data) => expectType<'a' | 'b'>(data),
|
|
75
73
|
})
|
|
76
74
|
expectType<'a' | 'b' | undefined>(unionTypeSync.data)
|
|
77
75
|
const unionTypeAsync = useQuery<'a' | 'b'>({
|
|
78
76
|
queryKey: key,
|
|
79
77
|
queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),
|
|
80
|
-
|
|
81
|
-
onSuccess: (data) => expectType<'a' | 'b'>(data),
|
|
82
78
|
})
|
|
83
79
|
expectType<'a' | 'b' | undefined>(unionTypeAsync.data)
|
|
84
80
|
|
|
@@ -448,255 +444,6 @@ describe('useQuery', () => {
|
|
|
448
444
|
})
|
|
449
445
|
})
|
|
450
446
|
|
|
451
|
-
it('should call onSuccess after a query has been fetched', async () => {
|
|
452
|
-
const key = queryKey()
|
|
453
|
-
const states: UseQueryResult<string>[] = []
|
|
454
|
-
const onSuccess = jest.fn()
|
|
455
|
-
|
|
456
|
-
function Page() {
|
|
457
|
-
const state = useQuery({
|
|
458
|
-
queryKey: key,
|
|
459
|
-
queryFn: async () => {
|
|
460
|
-
await sleep(10)
|
|
461
|
-
return 'data'
|
|
462
|
-
},
|
|
463
|
-
onSuccess,
|
|
464
|
-
})
|
|
465
|
-
states.push(state)
|
|
466
|
-
return <div>data: {state.data}</div>
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
470
|
-
|
|
471
|
-
await rendered.findByText('data: data')
|
|
472
|
-
expect(states.length).toBe(2)
|
|
473
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
474
|
-
expect(onSuccess).toHaveBeenCalledWith('data')
|
|
475
|
-
})
|
|
476
|
-
|
|
477
|
-
it('should call onSuccess after a query has been refetched', async () => {
|
|
478
|
-
const key = queryKey()
|
|
479
|
-
const states: UseQueryResult<string>[] = []
|
|
480
|
-
const onSuccess = jest.fn()
|
|
481
|
-
let count = 0
|
|
482
|
-
|
|
483
|
-
function Page() {
|
|
484
|
-
const state = useQuery({
|
|
485
|
-
queryKey: key,
|
|
486
|
-
queryFn: async () => {
|
|
487
|
-
count++
|
|
488
|
-
await sleep(10)
|
|
489
|
-
return 'data' + count
|
|
490
|
-
},
|
|
491
|
-
onSuccess,
|
|
492
|
-
})
|
|
493
|
-
|
|
494
|
-
states.push(state)
|
|
495
|
-
|
|
496
|
-
return (
|
|
497
|
-
<div>
|
|
498
|
-
<div>data: {state.data}</div>
|
|
499
|
-
<button onClick={() => state.refetch()}>refetch</button>
|
|
500
|
-
</div>
|
|
501
|
-
)
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
505
|
-
|
|
506
|
-
await rendered.findByText('data: data1')
|
|
507
|
-
fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
|
|
508
|
-
await rendered.findByText('data: data2')
|
|
509
|
-
|
|
510
|
-
expect(states.length).toBe(3) //pending, success, success after refetch
|
|
511
|
-
expect(count).toBe(2)
|
|
512
|
-
expect(onSuccess).toHaveBeenCalledTimes(2)
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
it('should call onSuccess after a disabled query has been fetched', async () => {
|
|
516
|
-
const key = queryKey()
|
|
517
|
-
const states: UseQueryResult<string>[] = []
|
|
518
|
-
const onSuccess = jest.fn()
|
|
519
|
-
|
|
520
|
-
function Page() {
|
|
521
|
-
const state = useQuery({
|
|
522
|
-
queryKey: key,
|
|
523
|
-
queryFn: () => 'data',
|
|
524
|
-
enabled: false,
|
|
525
|
-
onSuccess,
|
|
526
|
-
})
|
|
527
|
-
|
|
528
|
-
states.push(state)
|
|
529
|
-
|
|
530
|
-
return (
|
|
531
|
-
<div>
|
|
532
|
-
<div>isSuccess: {state.isSuccess ? 'true' : 'false'}</div>
|
|
533
|
-
<button onClick={() => state.refetch()}>refetch</button>
|
|
534
|
-
</div>
|
|
535
|
-
)
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
539
|
-
|
|
540
|
-
await waitFor(() => {
|
|
541
|
-
rendered.getByText('isSuccess: false')
|
|
542
|
-
})
|
|
543
|
-
|
|
544
|
-
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
545
|
-
|
|
546
|
-
await waitFor(() => {
|
|
547
|
-
rendered.getByText('isSuccess: true')
|
|
548
|
-
})
|
|
549
|
-
|
|
550
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
551
|
-
expect(onSuccess).toHaveBeenCalledWith('data')
|
|
552
|
-
})
|
|
553
|
-
|
|
554
|
-
it('should not call onSuccess if a component has unmounted', async () => {
|
|
555
|
-
const key = queryKey()
|
|
556
|
-
const states: UseQueryResult<string>[] = []
|
|
557
|
-
const onSuccess = jest.fn()
|
|
558
|
-
|
|
559
|
-
function Page() {
|
|
560
|
-
const [show, setShow] = React.useState(true)
|
|
561
|
-
|
|
562
|
-
React.useEffect(() => {
|
|
563
|
-
setShow(false)
|
|
564
|
-
}, [setShow])
|
|
565
|
-
|
|
566
|
-
return show ? <Component /> : null
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
function Component() {
|
|
570
|
-
const state = useQuery({
|
|
571
|
-
queryKey: key,
|
|
572
|
-
queryFn: async () => {
|
|
573
|
-
await sleep(10)
|
|
574
|
-
return 'data'
|
|
575
|
-
},
|
|
576
|
-
onSuccess,
|
|
577
|
-
})
|
|
578
|
-
states.push(state)
|
|
579
|
-
return null
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
renderWithClient(queryClient, <Page />)
|
|
583
|
-
|
|
584
|
-
await sleep(50)
|
|
585
|
-
expect(states.length).toBe(1)
|
|
586
|
-
expect(onSuccess).toHaveBeenCalledTimes(0)
|
|
587
|
-
})
|
|
588
|
-
|
|
589
|
-
it('should call onError after a query has been fetched with an error', async () => {
|
|
590
|
-
const key = queryKey()
|
|
591
|
-
const states: UseQueryResult<unknown>[] = []
|
|
592
|
-
const onError = jest.fn()
|
|
593
|
-
|
|
594
|
-
function Page() {
|
|
595
|
-
const state = useQuery<unknown>({
|
|
596
|
-
queryKey: key,
|
|
597
|
-
queryFn: () => Promise.reject(new Error('error')),
|
|
598
|
-
retry: false,
|
|
599
|
-
onError,
|
|
600
|
-
})
|
|
601
|
-
states.push(state)
|
|
602
|
-
return null
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
renderWithClient(queryClient, <Page />)
|
|
606
|
-
|
|
607
|
-
await sleep(10)
|
|
608
|
-
expect(states.length).toBe(2)
|
|
609
|
-
expect(onError).toHaveBeenCalledTimes(1)
|
|
610
|
-
expect(onError).toHaveBeenCalledWith(new Error('error'))
|
|
611
|
-
})
|
|
612
|
-
|
|
613
|
-
it('should not call onError when receiving a CancelledError', async () => {
|
|
614
|
-
const key = queryKey()
|
|
615
|
-
const onError = jest.fn()
|
|
616
|
-
|
|
617
|
-
function Page() {
|
|
618
|
-
const { status, fetchStatus } = useQuery({
|
|
619
|
-
queryKey: key,
|
|
620
|
-
queryFn: async () => {
|
|
621
|
-
await sleep(10)
|
|
622
|
-
return 23
|
|
623
|
-
},
|
|
624
|
-
|
|
625
|
-
onError,
|
|
626
|
-
})
|
|
627
|
-
return (
|
|
628
|
-
<span>
|
|
629
|
-
status: {status}, fetchStatus: {fetchStatus}
|
|
630
|
-
</span>
|
|
631
|
-
)
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
635
|
-
|
|
636
|
-
rendered.getByText('status: pending, fetchStatus: fetching')
|
|
637
|
-
|
|
638
|
-
await queryClient.cancelQueries({ queryKey: key })
|
|
639
|
-
// query cancellation will reset the query to it's initial state
|
|
640
|
-
await waitFor(() =>
|
|
641
|
-
rendered.getByText('status: pending, fetchStatus: idle'),
|
|
642
|
-
)
|
|
643
|
-
expect(onError).not.toHaveBeenCalled()
|
|
644
|
-
})
|
|
645
|
-
|
|
646
|
-
it('should call onSettled after a query has been fetched', async () => {
|
|
647
|
-
const key = queryKey()
|
|
648
|
-
const states: UseQueryResult<string>[] = []
|
|
649
|
-
const onSettled = jest.fn()
|
|
650
|
-
|
|
651
|
-
function Page() {
|
|
652
|
-
const state = useQuery({
|
|
653
|
-
queryKey: key,
|
|
654
|
-
queryFn: () => 'data',
|
|
655
|
-
onSettled,
|
|
656
|
-
})
|
|
657
|
-
states.push(state)
|
|
658
|
-
|
|
659
|
-
return <div>data: {state.data}</div>
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
663
|
-
|
|
664
|
-
await waitFor(() => {
|
|
665
|
-
rendered.getByText('data: data')
|
|
666
|
-
})
|
|
667
|
-
|
|
668
|
-
expect(states.length).toBe(2)
|
|
669
|
-
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
670
|
-
expect(onSettled).toHaveBeenCalledWith('data', null)
|
|
671
|
-
})
|
|
672
|
-
|
|
673
|
-
it('should call onSettled after a query has been fetched with an error', async () => {
|
|
674
|
-
const key = queryKey()
|
|
675
|
-
const onSettled = jest.fn()
|
|
676
|
-
const error = new Error('error')
|
|
677
|
-
|
|
678
|
-
function Page() {
|
|
679
|
-
const state = useQuery({
|
|
680
|
-
queryKey: key,
|
|
681
|
-
queryFn: async () => {
|
|
682
|
-
await sleep(10)
|
|
683
|
-
return Promise.reject(error)
|
|
684
|
-
},
|
|
685
|
-
retry: false,
|
|
686
|
-
onSettled,
|
|
687
|
-
})
|
|
688
|
-
return <div>status: {state.status}</div>
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
692
|
-
|
|
693
|
-
await waitFor(() => {
|
|
694
|
-
rendered.getByText('status: error')
|
|
695
|
-
})
|
|
696
|
-
expect(onSettled).toHaveBeenCalledTimes(1)
|
|
697
|
-
expect(onSettled).toHaveBeenCalledWith(undefined, error)
|
|
698
|
-
})
|
|
699
|
-
|
|
700
447
|
it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {
|
|
701
448
|
const key = queryKey()
|
|
702
449
|
let fetchCount = 0
|
|
@@ -1726,6 +1473,159 @@ describe('useQuery', () => {
|
|
|
1726
1473
|
})
|
|
1727
1474
|
})
|
|
1728
1475
|
|
|
1476
|
+
it('should keep the previous data when placeholderData is set and select fn transform is used', async () => {
|
|
1477
|
+
const key = queryKey()
|
|
1478
|
+
const states: UseQueryResult<number>[] = []
|
|
1479
|
+
|
|
1480
|
+
function Page() {
|
|
1481
|
+
const [count, setCount] = React.useState(0)
|
|
1482
|
+
|
|
1483
|
+
const state = useQuery({
|
|
1484
|
+
queryKey: [key, count],
|
|
1485
|
+
queryFn: async () => {
|
|
1486
|
+
await sleep(10)
|
|
1487
|
+
return {
|
|
1488
|
+
count,
|
|
1489
|
+
}
|
|
1490
|
+
},
|
|
1491
|
+
select(data) {
|
|
1492
|
+
return data.count
|
|
1493
|
+
},
|
|
1494
|
+
placeholderData: keepPreviousData,
|
|
1495
|
+
})
|
|
1496
|
+
|
|
1497
|
+
states.push(state)
|
|
1498
|
+
|
|
1499
|
+
return (
|
|
1500
|
+
<div>
|
|
1501
|
+
<div>data: {state.data}</div>
|
|
1502
|
+
<button onClick={() => setCount(1)}>setCount</button>
|
|
1503
|
+
</div>
|
|
1504
|
+
)
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
1508
|
+
|
|
1509
|
+
await waitFor(() => rendered.getByText('data: 0'))
|
|
1510
|
+
|
|
1511
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1512
|
+
|
|
1513
|
+
await waitFor(() => rendered.getByText('data: 1'))
|
|
1514
|
+
|
|
1515
|
+
// Initial
|
|
1516
|
+
expect(states[0]).toMatchObject({
|
|
1517
|
+
data: undefined,
|
|
1518
|
+
isFetching: true,
|
|
1519
|
+
isSuccess: false,
|
|
1520
|
+
isPlaceholderData: false,
|
|
1521
|
+
})
|
|
1522
|
+
// Fetched
|
|
1523
|
+
expect(states[1]).toMatchObject({
|
|
1524
|
+
data: 0,
|
|
1525
|
+
isFetching: false,
|
|
1526
|
+
isSuccess: true,
|
|
1527
|
+
isPlaceholderData: false,
|
|
1528
|
+
})
|
|
1529
|
+
// Set state
|
|
1530
|
+
expect(states[2]).toMatchObject({
|
|
1531
|
+
data: 0,
|
|
1532
|
+
isFetching: true,
|
|
1533
|
+
isSuccess: true,
|
|
1534
|
+
isPlaceholderData: true,
|
|
1535
|
+
})
|
|
1536
|
+
// New data
|
|
1537
|
+
expect(states[3]).toMatchObject({
|
|
1538
|
+
data: 1,
|
|
1539
|
+
isFetching: false,
|
|
1540
|
+
isSuccess: true,
|
|
1541
|
+
isPlaceholderData: false,
|
|
1542
|
+
})
|
|
1543
|
+
})
|
|
1544
|
+
|
|
1545
|
+
it('should show placeholderData between multiple pending queries when select fn transform is used', async () => {
|
|
1546
|
+
const key = queryKey()
|
|
1547
|
+
const states: UseQueryResult<number>[] = []
|
|
1548
|
+
|
|
1549
|
+
function Page() {
|
|
1550
|
+
const [count, setCount] = React.useState(0)
|
|
1551
|
+
|
|
1552
|
+
const state = useQuery({
|
|
1553
|
+
queryKey: [key, count],
|
|
1554
|
+
queryFn: async () => {
|
|
1555
|
+
await sleep(10)
|
|
1556
|
+
return {
|
|
1557
|
+
count,
|
|
1558
|
+
}
|
|
1559
|
+
},
|
|
1560
|
+
select(data) {
|
|
1561
|
+
return data.count
|
|
1562
|
+
},
|
|
1563
|
+
placeholderData: keepPreviousData,
|
|
1564
|
+
})
|
|
1565
|
+
|
|
1566
|
+
states.push(state)
|
|
1567
|
+
|
|
1568
|
+
return (
|
|
1569
|
+
<div>
|
|
1570
|
+
<div>data: {state.data}</div>
|
|
1571
|
+
<button onClick={() => setCount((prev) => prev + 1)}>setCount</button>
|
|
1572
|
+
</div>
|
|
1573
|
+
)
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
1577
|
+
|
|
1578
|
+
await waitFor(() => rendered.getByText('data: 0'))
|
|
1579
|
+
|
|
1580
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1581
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1582
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1583
|
+
|
|
1584
|
+
await waitFor(() => rendered.getByText('data: 3'))
|
|
1585
|
+
// Initial
|
|
1586
|
+
expect(states[0]).toMatchObject({
|
|
1587
|
+
data: undefined,
|
|
1588
|
+
isFetching: true,
|
|
1589
|
+
isSuccess: false,
|
|
1590
|
+
isPlaceholderData: false,
|
|
1591
|
+
})
|
|
1592
|
+
// Fetched
|
|
1593
|
+
expect(states[1]).toMatchObject({
|
|
1594
|
+
data: 0,
|
|
1595
|
+
isFetching: false,
|
|
1596
|
+
isSuccess: true,
|
|
1597
|
+
isPlaceholderData: false,
|
|
1598
|
+
})
|
|
1599
|
+
// Set state -> count = 1
|
|
1600
|
+
expect(states[2]).toMatchObject({
|
|
1601
|
+
data: 0,
|
|
1602
|
+
isFetching: true,
|
|
1603
|
+
isSuccess: true,
|
|
1604
|
+
isPlaceholderData: true,
|
|
1605
|
+
})
|
|
1606
|
+
// Set state -> count = 2
|
|
1607
|
+
expect(states[3]).toMatchObject({
|
|
1608
|
+
data: 0,
|
|
1609
|
+
isFetching: true,
|
|
1610
|
+
isSuccess: true,
|
|
1611
|
+
isPlaceholderData: true,
|
|
1612
|
+
})
|
|
1613
|
+
// Set state -> count = 3
|
|
1614
|
+
expect(states[4]).toMatchObject({
|
|
1615
|
+
data: 0,
|
|
1616
|
+
isFetching: true,
|
|
1617
|
+
isSuccess: true,
|
|
1618
|
+
isPlaceholderData: true,
|
|
1619
|
+
})
|
|
1620
|
+
// New data
|
|
1621
|
+
expect(states[5]).toMatchObject({
|
|
1622
|
+
data: 3,
|
|
1623
|
+
isFetching: false,
|
|
1624
|
+
isSuccess: true,
|
|
1625
|
+
isPlaceholderData: false,
|
|
1626
|
+
})
|
|
1627
|
+
})
|
|
1628
|
+
|
|
1729
1629
|
it('should transition to error state when placeholderData is set', async () => {
|
|
1730
1630
|
const key = queryKey()
|
|
1731
1631
|
const states: UseQueryResult<number>[] = []
|
|
@@ -2432,53 +2332,6 @@ describe('useQuery', () => {
|
|
|
2432
2332
|
expect(renders).toBe(2)
|
|
2433
2333
|
})
|
|
2434
2334
|
|
|
2435
|
-
it('should batch re-renders including hook callbacks', async () => {
|
|
2436
|
-
const key = queryKey()
|
|
2437
|
-
|
|
2438
|
-
let renders = 0
|
|
2439
|
-
let callbackCount = 0
|
|
2440
|
-
|
|
2441
|
-
const queryFn = async () => {
|
|
2442
|
-
await sleep(10)
|
|
2443
|
-
return 'data'
|
|
2444
|
-
}
|
|
2445
|
-
|
|
2446
|
-
function Page() {
|
|
2447
|
-
const [count, setCount] = React.useState(0)
|
|
2448
|
-
useQuery({
|
|
2449
|
-
queryKey: key,
|
|
2450
|
-
queryFn,
|
|
2451
|
-
onSuccess: () => {
|
|
2452
|
-
setCount((x) => x + 1)
|
|
2453
|
-
},
|
|
2454
|
-
})
|
|
2455
|
-
useQuery({
|
|
2456
|
-
queryKey: key,
|
|
2457
|
-
queryFn,
|
|
2458
|
-
onSuccess: () => {
|
|
2459
|
-
setCount((x) => x + 1)
|
|
2460
|
-
},
|
|
2461
|
-
})
|
|
2462
|
-
|
|
2463
|
-
React.useEffect(() => {
|
|
2464
|
-
renders++
|
|
2465
|
-
callbackCount = count
|
|
2466
|
-
})
|
|
2467
|
-
|
|
2468
|
-
return <div>count: {count}</div>
|
|
2469
|
-
}
|
|
2470
|
-
|
|
2471
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
2472
|
-
|
|
2473
|
-
await waitFor(() => rendered.getByText('count: 2'))
|
|
2474
|
-
|
|
2475
|
-
// Should be 3 instead of 5
|
|
2476
|
-
expect(renders).toBe(3)
|
|
2477
|
-
|
|
2478
|
-
// Both callbacks should have been executed
|
|
2479
|
-
expect(callbackCount).toBe(2)
|
|
2480
|
-
})
|
|
2481
|
-
|
|
2482
2335
|
it('should render latest data even if react has discarded certain renders', async () => {
|
|
2483
2336
|
const key = queryKey()
|
|
2484
2337
|
|
|
@@ -2584,7 +2437,7 @@ describe('useQuery', () => {
|
|
|
2584
2437
|
|
|
2585
2438
|
it('should not refetch query on focus when `enabled` is set to `false`', async () => {
|
|
2586
2439
|
const key = queryKey()
|
|
2587
|
-
const queryFn =
|
|
2440
|
+
const queryFn = vi.fn<unknown[], string>().mockReturnValue('data')
|
|
2588
2441
|
|
|
2589
2442
|
function Page() {
|
|
2590
2443
|
const { data = 'default' } = useQuery({
|
|
@@ -2895,7 +2748,7 @@ describe('useQuery', () => {
|
|
|
2895
2748
|
})
|
|
2896
2749
|
|
|
2897
2750
|
it('should throw error if queryFn throws and throwErrors is in use', async () => {
|
|
2898
|
-
const consoleMock =
|
|
2751
|
+
const consoleMock = vi
|
|
2899
2752
|
.spyOn(console, 'error')
|
|
2900
2753
|
.mockImplementation(() => undefined)
|
|
2901
2754
|
const key = queryKey()
|
|
@@ -2987,7 +2840,7 @@ describe('useQuery', () => {
|
|
|
2987
2840
|
})
|
|
2988
2841
|
|
|
2989
2842
|
it('should throw error instead of setting status when error should be thrown', async () => {
|
|
2990
|
-
const consoleMock =
|
|
2843
|
+
const consoleMock = vi
|
|
2991
2844
|
.spyOn(console, 'error')
|
|
2992
2845
|
.mockImplementation(() => undefined)
|
|
2993
2846
|
|
|
@@ -3355,7 +3208,7 @@ describe('useQuery', () => {
|
|
|
3355
3208
|
it('should retry specified number of times', async () => {
|
|
3356
3209
|
const key = queryKey()
|
|
3357
3210
|
|
|
3358
|
-
const queryFn =
|
|
3211
|
+
const queryFn = vi.fn<unknown[], unknown>()
|
|
3359
3212
|
queryFn.mockImplementation(() => {
|
|
3360
3213
|
return Promise.reject(new Error('Error test Barrett'))
|
|
3361
3214
|
})
|
|
@@ -3392,7 +3245,7 @@ describe('useQuery', () => {
|
|
|
3392
3245
|
it('should not retry if retry function `false`', async () => {
|
|
3393
3246
|
const key = queryKey()
|
|
3394
3247
|
|
|
3395
|
-
const queryFn =
|
|
3248
|
+
const queryFn = vi.fn<unknown[], unknown>()
|
|
3396
3249
|
|
|
3397
3250
|
queryFn.mockImplementationOnce(() => {
|
|
3398
3251
|
return Promise.reject(new Error('Error test Tanner'))
|
|
@@ -3438,7 +3291,7 @@ describe('useQuery', () => {
|
|
|
3438
3291
|
|
|
3439
3292
|
type DelayError = { delay: number }
|
|
3440
3293
|
|
|
3441
|
-
const queryFn =
|
|
3294
|
+
const queryFn = vi.fn<unknown[], unknown>()
|
|
3442
3295
|
queryFn.mockImplementation(() => {
|
|
3443
3296
|
return Promise.reject({ delay: 50 })
|
|
3444
3297
|
})
|
|
@@ -3631,10 +3484,10 @@ describe('useQuery', () => {
|
|
|
3631
3484
|
const key = queryKey()
|
|
3632
3485
|
const states: UseQueryResult<string>[] = []
|
|
3633
3486
|
|
|
3634
|
-
const queryFn =
|
|
3487
|
+
const queryFn = vi.fn<unknown[], string>()
|
|
3635
3488
|
queryFn.mockImplementation(() => 'data')
|
|
3636
3489
|
|
|
3637
|
-
const prefetchQueryFn =
|
|
3490
|
+
const prefetchQueryFn = vi.fn<unknown[], string>()
|
|
3638
3491
|
prefetchQueryFn.mockImplementation(() => 'not yet...')
|
|
3639
3492
|
|
|
3640
3493
|
await queryClient.prefetchQuery({
|
|
@@ -3662,10 +3515,10 @@ describe('useQuery', () => {
|
|
|
3662
3515
|
it('should not refetch if not stale after a prefetch', async () => {
|
|
3663
3516
|
const key = queryKey()
|
|
3664
3517
|
|
|
3665
|
-
const queryFn =
|
|
3518
|
+
const queryFn = vi.fn<unknown[], string>()
|
|
3666
3519
|
queryFn.mockImplementation(() => 'data')
|
|
3667
3520
|
|
|
3668
|
-
const prefetchQueryFn =
|
|
3521
|
+
const prefetchQueryFn = vi.fn<unknown[], Promise<string>>()
|
|
3669
3522
|
prefetchQueryFn.mockImplementation(async () => {
|
|
3670
3523
|
await sleep(10)
|
|
3671
3524
|
return 'not yet...'
|
|
@@ -3971,7 +3824,7 @@ describe('useQuery', () => {
|
|
|
3971
3824
|
|
|
3972
3825
|
it('it should support enabled:false in query object syntax', async () => {
|
|
3973
3826
|
const key = queryKey()
|
|
3974
|
-
const queryFn =
|
|
3827
|
+
const queryFn = vi.fn<unknown[], string>()
|
|
3975
3828
|
queryFn.mockImplementation(() => 'data')
|
|
3976
3829
|
|
|
3977
3830
|
function Page() {
|
|
@@ -4030,15 +3883,11 @@ describe('useQuery', () => {
|
|
|
4030
3883
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
4031
3884
|
|
|
4032
3885
|
await waitFor(() => rendered.getByText('fetched data'))
|
|
4033
|
-
|
|
4034
|
-
legacyFakeTimers: true,
|
|
4035
|
-
})
|
|
4036
|
-
const setTimeoutSpy = jest.spyOn(globalThis.window, 'setTimeout')
|
|
3886
|
+
const setTimeoutSpy = vi.spyOn(globalThis.window, 'setTimeout')
|
|
4037
3887
|
|
|
4038
3888
|
rendered.unmount()
|
|
4039
3889
|
|
|
4040
3890
|
expect(setTimeoutSpy).not.toHaveBeenCalled()
|
|
4041
|
-
jest.useRealTimers()
|
|
4042
3891
|
})
|
|
4043
3892
|
|
|
4044
3893
|
test('should schedule garbage collection, if gcTimeout is not set to infinity', async () => {
|
|
@@ -4057,10 +3906,7 @@ describe('useQuery', () => {
|
|
|
4057
3906
|
|
|
4058
3907
|
await waitFor(() => rendered.getByText('fetched data'))
|
|
4059
3908
|
|
|
4060
|
-
|
|
4061
|
-
legacyFakeTimers: true,
|
|
4062
|
-
})
|
|
4063
|
-
const setTimeoutSpy = jest.spyOn(globalThis.window, 'setTimeout')
|
|
3909
|
+
const setTimeoutSpy = vi.spyOn(globalThis.window, 'setTimeout')
|
|
4064
3910
|
|
|
4065
3911
|
rendered.unmount()
|
|
4066
3912
|
|
|
@@ -4068,13 +3914,12 @@ describe('useQuery', () => {
|
|
|
4068
3914
|
expect.any(Function),
|
|
4069
3915
|
1000 * 60 * 10,
|
|
4070
3916
|
)
|
|
4071
|
-
jest.useRealTimers()
|
|
4072
3917
|
})
|
|
4073
3918
|
|
|
4074
3919
|
it('should not cause memo churn when data does not change', async () => {
|
|
4075
3920
|
const key = queryKey()
|
|
4076
|
-
const queryFn =
|
|
4077
|
-
const memoFn =
|
|
3921
|
+
const queryFn = vi.fn<unknown[], string>().mockReturnValue('data')
|
|
3922
|
+
const memoFn = vi.fn()
|
|
4078
3923
|
|
|
4079
3924
|
function Page() {
|
|
4080
3925
|
const result = useQuery({
|
|
@@ -4281,7 +4126,7 @@ describe('useQuery', () => {
|
|
|
4281
4126
|
it('should refetch if any query instance becomes enabled', async () => {
|
|
4282
4127
|
const key = queryKey()
|
|
4283
4128
|
|
|
4284
|
-
const queryFn =
|
|
4129
|
+
const queryFn = vi.fn<unknown[], string>().mockReturnValue('data')
|
|
4285
4130
|
|
|
4286
4131
|
function Disabled() {
|
|
4287
4132
|
useQuery({ queryKey: key, queryFn, enabled: false })
|
|
@@ -4640,11 +4485,11 @@ describe('useQuery', () => {
|
|
|
4640
4485
|
|
|
4641
4486
|
it('should cancel the query function when there are no more subscriptions', async () => {
|
|
4642
4487
|
const key = queryKey()
|
|
4643
|
-
let cancelFn:
|
|
4488
|
+
let cancelFn: Mock = vi.fn()
|
|
4644
4489
|
|
|
4645
4490
|
const queryFn = ({ signal }: { signal?: AbortSignal }) => {
|
|
4646
4491
|
const promise = new Promise<string>((resolve, reject) => {
|
|
4647
|
-
cancelFn =
|
|
4492
|
+
cancelFn = vi.fn(() => reject('Cancelled'))
|
|
4648
4493
|
signal?.addEventListener('abort', cancelFn)
|
|
4649
4494
|
sleep(20).then(() => resolve('OK'))
|
|
4650
4495
|
})
|
|
@@ -4963,7 +4808,7 @@ describe('useQuery', () => {
|
|
|
4963
4808
|
})
|
|
4964
4809
|
|
|
4965
4810
|
it('should refetch when changed enabled to true in error state', async () => {
|
|
4966
|
-
const queryFn =
|
|
4811
|
+
const queryFn = vi.fn<unknown[], unknown>()
|
|
4967
4812
|
queryFn.mockImplementation(async () => {
|
|
4968
4813
|
await sleep(10)
|
|
4969
4814
|
return Promise.reject(new Error('Suspense Error Bingo'))
|
|
@@ -5979,36 +5824,6 @@ describe('useQuery', () => {
|
|
|
5979
5824
|
})
|
|
5980
5825
|
})
|
|
5981
5826
|
|
|
5982
|
-
it('setQueryData - should not call onSuccess callback of active observers', async () => {
|
|
5983
|
-
const key = queryKey()
|
|
5984
|
-
const onSuccess = jest.fn()
|
|
5985
|
-
|
|
5986
|
-
function Page() {
|
|
5987
|
-
const state = useQuery({
|
|
5988
|
-
queryKey: key,
|
|
5989
|
-
queryFn: () => 'data',
|
|
5990
|
-
onSuccess,
|
|
5991
|
-
})
|
|
5992
|
-
return (
|
|
5993
|
-
<div>
|
|
5994
|
-
<div>data: {state.data}</div>
|
|
5995
|
-
<button onClick={() => queryClient.setQueryData(key, 'newData')}>
|
|
5996
|
-
setQueryData
|
|
5997
|
-
</button>
|
|
5998
|
-
</div>
|
|
5999
|
-
)
|
|
6000
|
-
}
|
|
6001
|
-
|
|
6002
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
6003
|
-
|
|
6004
|
-
await waitFor(() => rendered.getByText('data: data'))
|
|
6005
|
-
fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i }))
|
|
6006
|
-
await waitFor(() => rendered.getByText('data: newData'))
|
|
6007
|
-
|
|
6008
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
6009
|
-
expect(onSuccess).toHaveBeenCalledWith('data')
|
|
6010
|
-
})
|
|
6011
|
-
|
|
6012
5827
|
it('setQueryData - should respect updatedAt', async () => {
|
|
6013
5828
|
const key = queryKey()
|
|
6014
5829
|
|