@tanstack/react-query 5.35.5 → 5.36.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query",
3
- "version": "5.35.5",
3
+ "version": "5.36.0",
4
4
  "description": "Hooks for managing, caching and syncing asynchronous and remote data in React",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -41,7 +41,7 @@
41
41
  "!build/codemods/**/__tests__"
42
42
  ],
43
43
  "dependencies": {
44
- "@tanstack/query-core": "5.35.5"
44
+ "@tanstack/query-core": "5.36.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/react": "^18.2.55",
@@ -81,7 +81,9 @@ describe('useInfiniteQuery', () => {
81
81
  isFetchedAfterMount: false,
82
82
  isFetching: true,
83
83
  isPaused: false,
84
+ isFetchNextPageError: false,
84
85
  isFetchingNextPage: false,
86
+ isFetchPreviousPageError: false,
85
87
  isFetchingPreviousPage: false,
86
88
  isLoading: true,
87
89
  isPending: true,
@@ -114,7 +116,9 @@ describe('useInfiniteQuery', () => {
114
116
  isFetchedAfterMount: true,
115
117
  isFetching: false,
116
118
  isPaused: false,
119
+ isFetchNextPageError: false,
117
120
  isFetchingNextPage: false,
121
+ isFetchPreviousPageError: false,
118
122
  isFetchingPreviousPage: false,
119
123
  isLoading: false,
120
124
  isPending: false,
@@ -595,6 +599,279 @@ describe('useInfiniteQuery', () => {
595
599
  })
596
600
  })
597
601
 
602
+ it('should return the correct states when refetch fails', async () => {
603
+ const key = queryKey()
604
+ const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []
605
+ let isRefetch = false
606
+
607
+ function Page() {
608
+ const state = useInfiniteQuery({
609
+ queryKey: key,
610
+ queryFn: async ({ pageParam }) => {
611
+ await sleep(10)
612
+ if (isRefetch) {
613
+ throw new Error()
614
+ } else {
615
+ return Number(pageParam)
616
+ }
617
+ },
618
+ initialPageParam: 10,
619
+ getPreviousPageParam: (firstPage) => firstPage - 1,
620
+ getNextPageParam: (lastPage) => lastPage + 1,
621
+ notifyOnChangeProps: 'all',
622
+ retry: false,
623
+ })
624
+
625
+ states.push(state)
626
+
627
+ return (
628
+ <div>
629
+ <button
630
+ onClick={() => {
631
+ isRefetch = true
632
+ state.refetch()
633
+ }}
634
+ >
635
+ refetch
636
+ </button>
637
+ <div>data: {state.data?.pages.join(',') ?? 'null'}</div>
638
+ <div>isFetching: {String(state.isFetching)}</div>
639
+ </div>
640
+ )
641
+ }
642
+
643
+ const rendered = renderWithClient(queryClient, <Page />)
644
+
645
+ await waitFor(() => rendered.getByText('data: 10'))
646
+ fireEvent.click(rendered.getByRole('button', { name: /refetch/i }))
647
+
648
+ await waitFor(() => rendered.getByText('isFetching: false'))
649
+ await waitFor(() => expect(states.length).toBe(4))
650
+
651
+ // Initial fetch
652
+ expect(states[0]).toMatchObject({
653
+ data: undefined,
654
+ isFetching: true,
655
+ isFetchNextPageError: false,
656
+ isFetchingNextPage: false,
657
+ isFetchPreviousPageError: false,
658
+ isFetchingPreviousPage: false,
659
+ isRefetchError: false,
660
+ isRefetching: false,
661
+ })
662
+ // Initial fetch done
663
+ expect(states[1]).toMatchObject({
664
+ data: { pages: [10] },
665
+ isFetching: false,
666
+ isFetchNextPageError: false,
667
+ isFetchingNextPage: false,
668
+ isFetchPreviousPageError: false,
669
+ isFetchingPreviousPage: false,
670
+ isRefetchError: false,
671
+ isRefetching: false,
672
+ })
673
+ // Refetch
674
+ expect(states[2]).toMatchObject({
675
+ data: { pages: [10] },
676
+ isFetching: true,
677
+ isFetchNextPageError: false,
678
+ isFetchingNextPage: false,
679
+ isFetchPreviousPageError: false,
680
+ isFetchingPreviousPage: false,
681
+ isRefetchError: false,
682
+ isRefetching: true,
683
+ })
684
+ // Refetch failed
685
+ expect(states[3]).toMatchObject({
686
+ data: { pages: [10] },
687
+ isFetching: false,
688
+ isFetchNextPageError: false,
689
+ isFetchingNextPage: false,
690
+ isFetchPreviousPageError: false,
691
+ isFetchingPreviousPage: false,
692
+ isRefetchError: true,
693
+ isRefetching: false,
694
+ })
695
+ })
696
+
697
+ it('should return the correct states when fetchNextPage fails', async () => {
698
+ const key = queryKey()
699
+ const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []
700
+
701
+ function Page() {
702
+ const state = useInfiniteQuery({
703
+ queryKey: key,
704
+ queryFn: async ({ pageParam }) => {
705
+ await sleep(10)
706
+ if (pageParam !== 10) {
707
+ throw new Error()
708
+ } else {
709
+ return Number(pageParam)
710
+ }
711
+ },
712
+ initialPageParam: 10,
713
+ getPreviousPageParam: (firstPage) => firstPage - 1,
714
+ getNextPageParam: (lastPage) => lastPage + 1,
715
+ notifyOnChangeProps: 'all',
716
+ retry: false,
717
+ })
718
+
719
+ states.push(state)
720
+
721
+ return (
722
+ <div>
723
+ <button onClick={() => state.fetchNextPage()}>fetchNextPage</button>
724
+ <div>data: {state.data?.pages.join(',') ?? 'null'}</div>
725
+ <div>isFetching: {String(state.isFetching)}</div>
726
+ </div>
727
+ )
728
+ }
729
+
730
+ const rendered = renderWithClient(queryClient, <Page />)
731
+
732
+ await waitFor(() => rendered.getByText('data: 10'))
733
+ fireEvent.click(rendered.getByRole('button', { name: /fetchNextPage/i }))
734
+
735
+ await waitFor(() => rendered.getByText('isFetching: false'))
736
+ await waitFor(() => expect(states.length).toBe(4))
737
+
738
+ // Initial fetch
739
+ expect(states[0]).toMatchObject({
740
+ data: undefined,
741
+ isFetching: true,
742
+ isFetchNextPageError: false,
743
+ isFetchingNextPage: false,
744
+ isFetchPreviousPageError: false,
745
+ isFetchingPreviousPage: false,
746
+ isRefetchError: false,
747
+ isRefetching: false,
748
+ })
749
+ // Initial fetch done
750
+ expect(states[1]).toMatchObject({
751
+ data: { pages: [10] },
752
+ isFetching: false,
753
+ isFetchNextPageError: false,
754
+ isFetchingNextPage: false,
755
+ isFetchPreviousPageError: false,
756
+ isFetchingPreviousPage: false,
757
+ isRefetchError: false,
758
+ isRefetching: false,
759
+ })
760
+ // Fetch next page
761
+ expect(states[2]).toMatchObject({
762
+ data: { pages: [10] },
763
+ isFetching: true,
764
+ isFetchNextPageError: false,
765
+ isFetchingNextPage: true,
766
+ isFetchPreviousPageError: false,
767
+ isFetchingPreviousPage: false,
768
+ isRefetchError: false,
769
+ isRefetching: false,
770
+ })
771
+ // Fetch next page failed
772
+ expect(states[3]).toMatchObject({
773
+ data: { pages: [10] },
774
+ isFetching: false,
775
+ isFetchNextPageError: true,
776
+ isFetchingNextPage: false,
777
+ isFetchPreviousPageError: false,
778
+ isFetchingPreviousPage: false,
779
+ isRefetchError: false,
780
+ isRefetching: false,
781
+ })
782
+ })
783
+
784
+ it('should return the correct states when fetchPreviousPage fails', async () => {
785
+ const key = queryKey()
786
+ const states: Array<UseInfiniteQueryResult<InfiniteData<number>>> = []
787
+
788
+ function Page() {
789
+ const state = useInfiniteQuery({
790
+ queryKey: key,
791
+ queryFn: async ({ pageParam }) => {
792
+ await sleep(10)
793
+ if (pageParam !== 10) {
794
+ throw new Error()
795
+ } else {
796
+ return Number(pageParam)
797
+ }
798
+ },
799
+ initialPageParam: 10,
800
+ getPreviousPageParam: (firstPage) => firstPage - 1,
801
+ getNextPageParam: (lastPage) => lastPage + 1,
802
+ notifyOnChangeProps: 'all',
803
+ retry: false,
804
+ })
805
+
806
+ states.push(state)
807
+
808
+ return (
809
+ <div>
810
+ <button onClick={() => state.fetchPreviousPage()}>
811
+ fetchPreviousPage
812
+ </button>
813
+ <div>data: {state.data?.pages.join(',') ?? 'null'}</div>
814
+ <div>isFetching: {String(state.isFetching)}</div>
815
+ </div>
816
+ )
817
+ }
818
+
819
+ const rendered = renderWithClient(queryClient, <Page />)
820
+
821
+ await waitFor(() => rendered.getByText('data: 10'))
822
+ fireEvent.click(
823
+ rendered.getByRole('button', { name: /fetchPreviousPage/i }),
824
+ )
825
+
826
+ await waitFor(() => rendered.getByText('isFetching: false'))
827
+ await waitFor(() => expect(states.length).toBe(4))
828
+
829
+ // Initial fetch
830
+ expect(states[0]).toMatchObject({
831
+ data: undefined,
832
+ isFetching: true,
833
+ isFetchNextPageError: false,
834
+ isFetchingNextPage: false,
835
+ isFetchPreviousPageError: false,
836
+ isFetchingPreviousPage: false,
837
+ isRefetchError: false,
838
+ isRefetching: false,
839
+ })
840
+ // Initial fetch done
841
+ expect(states[1]).toMatchObject({
842
+ data: { pages: [10] },
843
+ isFetching: false,
844
+ isFetchNextPageError: false,
845
+ isFetchingNextPage: false,
846
+ isFetchPreviousPageError: false,
847
+ isFetchingPreviousPage: false,
848
+ isRefetchError: false,
849
+ isRefetching: false,
850
+ })
851
+ // Fetch previous page
852
+ expect(states[2]).toMatchObject({
853
+ data: { pages: [10] },
854
+ isFetching: true,
855
+ isFetchNextPageError: false,
856
+ isFetchingNextPage: false,
857
+ isFetchPreviousPageError: false,
858
+ isFetchingPreviousPage: true,
859
+ isRefetchError: false,
860
+ isRefetching: false,
861
+ })
862
+ // Fetch previous page failed
863
+ expect(states[3]).toMatchObject({
864
+ data: { pages: [10] },
865
+ isFetching: false,
866
+ isFetchNextPageError: false,
867
+ isFetchingNextPage: false,
868
+ isFetchPreviousPageError: true,
869
+ isFetchingPreviousPage: false,
870
+ isRefetchError: false,
871
+ isRefetching: false,
872
+ })
873
+ })
874
+
598
875
  it('should silently cancel any ongoing fetch when fetching more', async () => {
599
876
  const key = queryKey()
600
877