@tanstack/react-query 5.0.0-alpha.9 → 5.0.0-alpha.91
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/codemods/remove-overloads/remove-overloads.js +59 -0
- package/build/codemods/remove-overloads/transformers/filter-aware-usage-transformer.js +153 -0
- package/build/codemods/remove-overloads/transformers/query-fn-aware-usage-transformer.js +188 -0
- package/build/codemods/remove-overloads/utils/index.js +124 -0
- package/build/codemods/remove-overloads/utils/unknown-usage-error.js +27 -0
- package/build/codemods/rename-hydrate/rename-hydrate.js +55 -0
- package/build/codemods/rename-properties/rename-properties.js +41 -0
- package/build/codemods/src/utils/index.js +205 -0
- package/build/codemods/src/v4/key-transformation.js +138 -0
- package/build/codemods/src/v4/replace-import-specifier.js +25 -0
- package/build/codemods/transformers/query-cache-transformer.js +116 -0
- package/build/codemods/transformers/query-client-transformer.js +48 -0
- package/build/codemods/transformers/use-query-like-transformer.js +32 -0
- package/build/codemods/utils/replacers/key-replacer.js +164 -0
- package/build/legacy/HydrationBoundary.cjs +60 -0
- package/build/legacy/HydrationBoundary.cjs.map +1 -0
- package/build/legacy/HydrationBoundary.d.cts +12 -0
- package/build/legacy/HydrationBoundary.d.ts +12 -0
- package/build/legacy/HydrationBoundary.js +26 -0
- package/build/legacy/HydrationBoundary.js.map +1 -0
- package/build/legacy/QueryClientProvider.cjs +71 -0
- package/build/legacy/QueryClientProvider.cjs.map +1 -0
- package/build/legacy/QueryClientProvider.d.cts +12 -0
- package/build/legacy/QueryClientProvider.d.ts +12 -0
- package/build/legacy/QueryClientProvider.js +35 -0
- package/build/legacy/QueryClientProvider.js.map +1 -0
- package/build/legacy/QueryErrorResetBoundary.cjs +66 -0
- package/build/legacy/QueryErrorResetBoundary.cjs.map +1 -0
- package/build/legacy/QueryErrorResetBoundary.d.cts +14 -0
- package/build/legacy/QueryErrorResetBoundary.d.ts +14 -0
- package/build/legacy/QueryErrorResetBoundary.js +31 -0
- package/build/legacy/QueryErrorResetBoundary.js.map +1 -0
- package/build/legacy/errorBoundaryUtils.cjs +67 -0
- package/build/legacy/errorBoundaryUtils.cjs.map +1 -0
- package/build/legacy/errorBoundaryUtils.d.cts +14 -0
- package/build/legacy/errorBoundaryUtils.d.ts +14 -0
- package/build/legacy/errorBoundaryUtils.js +31 -0
- package/build/legacy/errorBoundaryUtils.js.map +1 -0
- package/build/legacy/index.cjs +85 -0
- package/build/legacy/index.cjs.map +1 -0
- package/build/legacy/index.d.cts +17 -0
- package/build/legacy/index.d.ts +17 -0
- package/build/legacy/index.js +46 -0
- package/build/legacy/index.js.map +1 -0
- package/build/legacy/infiniteQueryOptions.cjs +33 -0
- package/build/legacy/infiniteQueryOptions.cjs.map +1 -0
- package/build/legacy/infiniteQueryOptions.d.cts +13 -0
- package/build/legacy/infiniteQueryOptions.d.ts +13 -0
- package/build/legacy/infiniteQueryOptions.js +8 -0
- package/build/legacy/infiniteQueryOptions.js.map +1 -0
- package/build/legacy/isRestoring.cjs +47 -0
- package/build/legacy/isRestoring.cjs.map +1 -0
- package/build/legacy/isRestoring.d.cts +6 -0
- package/build/legacy/isRestoring.d.ts +6 -0
- package/build/legacy/isRestoring.js +12 -0
- package/build/legacy/isRestoring.js.map +1 -0
- package/build/legacy/queryOptions.cjs +33 -0
- package/build/legacy/queryOptions.cjs.map +1 -0
- package/build/legacy/queryOptions.d.cts +13 -0
- package/build/legacy/queryOptions.d.ts +13 -0
- package/build/legacy/queryOptions.js +8 -0
- package/build/legacy/queryOptions.js.map +1 -0
- package/build/legacy/suspense.cjs +48 -0
- package/build/legacy/suspense.cjs.map +1 -0
- package/build/legacy/suspense.d.cts +10 -0
- package/build/legacy/suspense.d.ts +10 -0
- package/build/legacy/suspense.js +20 -0
- package/build/legacy/suspense.js.map +1 -0
- package/build/legacy/types.cjs +19 -0
- package/build/legacy/types.cjs.map +1 -0
- package/build/legacy/types.d.cts +34 -0
- package/build/legacy/types.d.ts +34 -0
- package/build/legacy/types.js +1 -0
- package/build/legacy/types.js.map +1 -0
- package/build/legacy/useBaseQuery.cjs +92 -0
- package/build/legacy/useBaseQuery.cjs.map +1 -0
- package/build/legacy/useBaseQuery.d.cts +92 -0
- package/build/legacy/useBaseQuery.d.ts +92 -0
- package/build/legacy/useBaseQuery.js +62 -0
- package/build/legacy/useBaseQuery.js.map +1 -0
- package/build/legacy/useInfiniteQuery.cjs +41 -0
- package/build/legacy/useInfiniteQuery.cjs.map +1 -0
- package/build/legacy/useInfiniteQuery.d.cts +8 -0
- package/build/legacy/useInfiniteQuery.d.ts +8 -0
- package/build/legacy/useInfiniteQuery.js +17 -0
- package/build/legacy/useInfiniteQuery.js.map +1 -0
- package/build/legacy/useIsFetching.cjs +56 -0
- package/build/legacy/useIsFetching.cjs.map +1 -0
- package/build/legacy/useIsFetching.d.cts +5 -0
- package/build/legacy/useIsFetching.d.ts +5 -0
- package/build/legacy/useIsFetching.js +22 -0
- package/build/legacy/useIsFetching.js.map +1 -0
- package/build/legacy/useMutation.cjs +77 -0
- package/build/legacy/useMutation.cjs.map +1 -0
- package/build/legacy/useMutation.d.cts +6 -0
- package/build/legacy/useMutation.d.ts +6 -0
- package/build/legacy/useMutation.js +43 -0
- package/build/legacy/useMutation.js.map +1 -0
- package/build/legacy/useMutationState.cjs +88 -0
- package/build/legacy/useMutationState.cjs.map +1 -0
- package/build/legacy/useMutationState.d.cts +10 -0
- package/build/legacy/useMutationState.d.ts +10 -0
- package/build/legacy/useMutationState.js +53 -0
- package/build/legacy/useMutationState.js.map +1 -0
- package/build/legacy/useQueries.cjs +128 -0
- package/build/legacy/useQueries.cjs.map +1 -0
- package/build/legacy/useQueries.d.cts +53 -0
- package/build/{lib → legacy}/useQueries.d.ts +14 -11
- package/build/legacy/useQueries.js +103 -0
- package/build/legacy/useQueries.js.map +1 -0
- package/build/legacy/useQuery.cjs +36 -0
- package/build/legacy/useQuery.cjs.map +1 -0
- package/build/legacy/useQuery.d.cts +8 -0
- package/build/legacy/useQuery.d.ts +8 -0
- package/build/legacy/useQuery.js +12 -0
- package/build/legacy/useQuery.js.map +1 -0
- package/build/legacy/useSuspenseInfiniteQuery.cjs +46 -0
- package/build/legacy/useSuspenseInfiniteQuery.cjs.map +1 -0
- package/build/legacy/useSuspenseInfiniteQuery.d.cts +6 -0
- package/build/legacy/useSuspenseInfiniteQuery.d.ts +6 -0
- package/build/legacy/useSuspenseInfiniteQuery.js +22 -0
- package/build/legacy/useSuspenseInfiniteQuery.js.map +1 -0
- package/build/legacy/useSuspenseQuery.cjs +45 -0
- package/build/legacy/useSuspenseQuery.cjs.map +1 -0
- package/build/legacy/useSuspenseQuery.d.cts +6 -0
- package/build/legacy/useSuspenseQuery.d.ts +6 -0
- package/build/legacy/useSuspenseQuery.js +21 -0
- package/build/legacy/useSuspenseQuery.js.map +1 -0
- package/build/legacy/utils.cjs +36 -0
- package/build/legacy/utils.cjs.map +1 -0
- package/build/legacy/utils.d.cts +3 -0
- package/build/legacy/utils.d.ts +3 -0
- package/build/legacy/utils.js +11 -0
- package/build/legacy/utils.js.map +1 -0
- package/build/modern/HydrationBoundary.cjs +60 -0
- package/build/modern/HydrationBoundary.cjs.map +1 -0
- package/build/modern/HydrationBoundary.d.cts +12 -0
- package/build/modern/HydrationBoundary.d.ts +12 -0
- package/build/modern/HydrationBoundary.js +26 -0
- package/build/modern/HydrationBoundary.js.map +1 -0
- package/build/modern/QueryClientProvider.cjs +71 -0
- package/build/modern/QueryClientProvider.cjs.map +1 -0
- package/build/modern/QueryClientProvider.d.cts +12 -0
- package/build/modern/QueryClientProvider.d.ts +12 -0
- package/build/modern/QueryClientProvider.js +35 -0
- package/build/modern/QueryClientProvider.js.map +1 -0
- package/build/modern/QueryErrorResetBoundary.cjs +66 -0
- package/build/modern/QueryErrorResetBoundary.cjs.map +1 -0
- package/build/modern/QueryErrorResetBoundary.d.cts +14 -0
- package/build/modern/QueryErrorResetBoundary.d.ts +14 -0
- package/build/modern/QueryErrorResetBoundary.js +31 -0
- package/build/modern/QueryErrorResetBoundary.js.map +1 -0
- package/build/modern/errorBoundaryUtils.cjs +67 -0
- package/build/modern/errorBoundaryUtils.cjs.map +1 -0
- package/build/modern/errorBoundaryUtils.d.cts +14 -0
- package/build/modern/errorBoundaryUtils.d.ts +14 -0
- package/build/modern/errorBoundaryUtils.js +31 -0
- package/build/modern/errorBoundaryUtils.js.map +1 -0
- package/build/modern/index.cjs +85 -0
- package/build/modern/index.cjs.map +1 -0
- package/build/modern/index.d.cts +17 -0
- package/build/modern/index.d.ts +17 -0
- package/build/modern/index.js +46 -0
- package/build/modern/index.js.map +1 -0
- package/build/modern/infiniteQueryOptions.cjs +33 -0
- package/build/modern/infiniteQueryOptions.cjs.map +1 -0
- package/build/modern/infiniteQueryOptions.d.cts +13 -0
- package/build/modern/infiniteQueryOptions.d.ts +13 -0
- package/build/modern/infiniteQueryOptions.js +8 -0
- package/build/modern/infiniteQueryOptions.js.map +1 -0
- package/build/modern/isRestoring.cjs +47 -0
- package/build/modern/isRestoring.cjs.map +1 -0
- package/build/modern/isRestoring.d.cts +6 -0
- package/build/modern/isRestoring.d.ts +6 -0
- package/build/modern/isRestoring.js +12 -0
- package/build/modern/isRestoring.js.map +1 -0
- package/build/modern/queryOptions.cjs +33 -0
- package/build/modern/queryOptions.cjs.map +1 -0
- package/build/modern/queryOptions.d.cts +13 -0
- package/build/modern/queryOptions.d.ts +13 -0
- package/build/modern/queryOptions.js +8 -0
- package/build/modern/queryOptions.js.map +1 -0
- package/build/modern/suspense.cjs +48 -0
- package/build/modern/suspense.cjs.map +1 -0
- package/build/modern/suspense.d.cts +10 -0
- package/build/modern/suspense.d.ts +10 -0
- package/build/modern/suspense.js +20 -0
- package/build/modern/suspense.js.map +1 -0
- package/build/modern/types.cjs +19 -0
- package/build/modern/types.cjs.map +1 -0
- package/build/modern/types.d.cts +34 -0
- package/build/modern/types.d.ts +34 -0
- package/build/modern/types.js +1 -0
- package/build/modern/types.js.map +1 -0
- package/build/modern/useBaseQuery.cjs +92 -0
- package/build/modern/useBaseQuery.cjs.map +1 -0
- package/build/modern/useBaseQuery.d.cts +92 -0
- package/build/modern/useBaseQuery.d.ts +92 -0
- package/build/modern/useBaseQuery.js +62 -0
- package/build/modern/useBaseQuery.js.map +1 -0
- package/build/modern/useInfiniteQuery.cjs +41 -0
- package/build/modern/useInfiniteQuery.cjs.map +1 -0
- package/build/modern/useInfiniteQuery.d.cts +8 -0
- package/build/modern/useInfiniteQuery.d.ts +8 -0
- package/build/modern/useInfiniteQuery.js +17 -0
- package/build/modern/useInfiniteQuery.js.map +1 -0
- package/build/modern/useIsFetching.cjs +56 -0
- package/build/modern/useIsFetching.cjs.map +1 -0
- package/build/modern/useIsFetching.d.cts +5 -0
- package/build/modern/useIsFetching.d.ts +5 -0
- package/build/modern/useIsFetching.js +22 -0
- package/build/modern/useIsFetching.js.map +1 -0
- package/build/modern/useMutation.cjs +77 -0
- package/build/modern/useMutation.cjs.map +1 -0
- package/build/modern/useMutation.d.cts +6 -0
- package/build/modern/useMutation.d.ts +6 -0
- package/build/modern/useMutation.js +43 -0
- package/build/modern/useMutation.js.map +1 -0
- package/build/modern/useMutationState.cjs +88 -0
- package/build/modern/useMutationState.cjs.map +1 -0
- package/build/modern/useMutationState.d.cts +10 -0
- package/build/modern/useMutationState.d.ts +10 -0
- package/build/modern/useMutationState.js +53 -0
- package/build/modern/useMutationState.js.map +1 -0
- package/build/modern/useQueries.cjs +125 -0
- package/build/modern/useQueries.cjs.map +1 -0
- package/build/modern/useQueries.d.cts +53 -0
- package/build/modern/useQueries.d.ts +53 -0
- package/build/modern/useQueries.js +100 -0
- package/build/modern/useQueries.js.map +1 -0
- package/build/modern/useQuery.cjs +36 -0
- package/build/modern/useQuery.cjs.map +1 -0
- package/build/modern/useQuery.d.cts +8 -0
- package/build/modern/useQuery.d.ts +8 -0
- package/build/modern/useQuery.js +12 -0
- package/build/modern/useQuery.js.map +1 -0
- package/build/modern/useSuspenseInfiniteQuery.cjs +46 -0
- package/build/modern/useSuspenseInfiniteQuery.cjs.map +1 -0
- package/build/modern/useSuspenseInfiniteQuery.d.cts +6 -0
- package/build/modern/useSuspenseInfiniteQuery.d.ts +6 -0
- package/build/modern/useSuspenseInfiniteQuery.js +22 -0
- package/build/modern/useSuspenseInfiniteQuery.js.map +1 -0
- package/build/modern/useSuspenseQuery.cjs +45 -0
- package/build/modern/useSuspenseQuery.cjs.map +1 -0
- package/build/modern/useSuspenseQuery.d.cts +6 -0
- package/build/modern/useSuspenseQuery.d.ts +6 -0
- package/build/modern/useSuspenseQuery.js +21 -0
- package/build/modern/useSuspenseQuery.js.map +1 -0
- package/build/modern/utils.cjs +36 -0
- package/build/modern/utils.cjs.map +1 -0
- package/build/modern/utils.d.cts +3 -0
- package/build/modern/utils.d.ts +3 -0
- package/build/modern/utils.js +11 -0
- package/build/modern/utils.js.map +1 -0
- package/package.json +29 -17
- package/src/HydrationBoundary.tsx +1 -1
- package/src/__tests__/HydrationBoundary.test.tsx +5 -5
- package/src/__tests__/QueryClientProvider.test.tsx +2 -2
- package/src/__tests__/QueryResetErrorBoundary.test.tsx +753 -621
- package/src/__tests__/ssr-hydration.test.tsx +4 -4
- package/src/__tests__/ssr.test.tsx +2 -2
- package/src/__tests__/suspense.test.tsx +8 -90
- package/src/__tests__/useInfiniteQuery.test.tsx +36 -74
- package/src/__tests__/useInfiniteQuery.type.test.tsx +2 -29
- package/src/__tests__/useIsFetching.test.tsx +1 -1
- package/src/__tests__/useMutation.test.tsx +22 -23
- package/src/__tests__/useMutationState.test.tsx +23 -0
- package/src/__tests__/useQueries.test.tsx +214 -91
- package/src/__tests__/useQuery.test.tsx +691 -551
- package/src/__tests__/useQuery.types.test.tsx +22 -1
- package/src/__tests__/utils.tsx +11 -5
- package/src/errorBoundaryUtils.ts +7 -7
- package/src/index.ts +4 -0
- package/src/infiniteQueryOptions.ts +93 -0
- package/src/queryOptions.ts +42 -0
- package/src/suspense.ts +9 -15
- package/src/types.ts +50 -8
- package/src/useBaseQuery.ts +14 -26
- package/src/useInfiniteQuery.ts +50 -7
- package/src/useIsFetching.ts +1 -1
- package/src/useMutation.ts +4 -4
- package/src/useMutationState.ts +8 -8
- package/src/useQueries.ts +53 -36
- package/src/useQuery.ts +6 -21
- package/src/useSuspenseInfiniteQuery.ts +47 -0
- package/src/useSuspenseQuery.ts +26 -0
- package/build/lib/HydrationBoundary.d.ts +0 -9
- package/build/lib/HydrationBoundary.esm.js +0 -29
- package/build/lib/HydrationBoundary.esm.js.map +0 -1
- package/build/lib/HydrationBoundary.js +0 -50
- package/build/lib/HydrationBoundary.js.map +0 -1
- package/build/lib/HydrationBoundary.mjs +0 -29
- package/build/lib/HydrationBoundary.mjs.map +0 -1
- package/build/lib/QueryClientProvider.d.ts +0 -9
- package/build/lib/QueryClientProvider.esm.js +0 -31
- package/build/lib/QueryClientProvider.esm.js.map +0 -1
- package/build/lib/QueryClientProvider.js +0 -54
- package/build/lib/QueryClientProvider.js.map +0 -1
- package/build/lib/QueryClientProvider.mjs +0 -31
- package/build/lib/QueryClientProvider.mjs.map +0 -1
- package/build/lib/QueryErrorResetBoundary.d.ts +0 -11
- package/build/lib/QueryErrorResetBoundary.esm.js +0 -38
- package/build/lib/QueryErrorResetBoundary.esm.js.map +0 -1
- package/build/lib/QueryErrorResetBoundary.js +0 -60
- package/build/lib/QueryErrorResetBoundary.js.map +0 -1
- package/build/lib/QueryErrorResetBoundary.mjs +0 -38
- package/build/lib/QueryErrorResetBoundary.mjs.map +0 -1
- package/build/lib/__tests__/HydrationBoundary.test.d.ts +0 -1
- package/build/lib/__tests__/QueryClientProvider.test.d.ts +0 -1
- package/build/lib/__tests__/QueryResetErrorBoundary.test.d.ts +0 -6
- package/build/lib/__tests__/ssr-hydration.test.d.ts +0 -1
- package/build/lib/__tests__/ssr.test.d.ts +0 -1
- package/build/lib/__tests__/suspense.test.d.ts +0 -1
- package/build/lib/__tests__/useInfiniteQuery.test.d.ts +0 -1
- package/build/lib/__tests__/useInfiniteQuery.type.test.d.ts +0 -1
- package/build/lib/__tests__/useIsFetching.test.d.ts +0 -1
- package/build/lib/__tests__/useMutation.test.d.ts +0 -1
- package/build/lib/__tests__/useMutationState.test.d.ts +0 -1
- package/build/lib/__tests__/useQueries.test.d.ts +0 -1
- package/build/lib/__tests__/useQuery.test.d.ts +0 -1
- package/build/lib/__tests__/useQuery.types.test.d.ts +0 -1
- package/build/lib/__tests__/utils.d.ts +0 -28
- package/build/lib/errorBoundaryUtils.d.ts +0 -10
- package/build/lib/errorBoundaryUtils.esm.js +0 -28
- package/build/lib/errorBoundaryUtils.esm.js.map +0 -1
- package/build/lib/errorBoundaryUtils.js +0 -51
- package/build/lib/errorBoundaryUtils.js.map +0 -1
- package/build/lib/errorBoundaryUtils.mjs +0 -28
- package/build/lib/errorBoundaryUtils.mjs.map +0 -1
- package/build/lib/index.d.ts +0 -16
- package/build/lib/index.esm.js +0 -12
- package/build/lib/index.esm.js.map +0 -1
- package/build/lib/index.js +0 -38
- package/build/lib/index.js.map +0 -1
- package/build/lib/index.mjs +0 -12
- package/build/lib/index.mjs.map +0 -1
- package/build/lib/isRestoring.d.ts +0 -3
- package/build/lib/isRestoring.esm.js +0 -9
- package/build/lib/isRestoring.esm.js.map +0 -1
- package/build/lib/isRestoring.js +0 -31
- package/build/lib/isRestoring.js.map +0 -1
- package/build/lib/isRestoring.mjs +0 -9
- package/build/lib/isRestoring.mjs.map +0 -1
- package/build/lib/suspense.d.ts +0 -9
- package/build/lib/suspense.esm.js +0 -24
- package/build/lib/suspense.esm.js.map +0 -1
- package/build/lib/suspense.js +0 -29
- package/build/lib/suspense.js.map +0 -1
- package/build/lib/suspense.mjs +0 -24
- package/build/lib/suspense.mjs.map +0 -1
- package/build/lib/types.d.ts +0 -26
- package/build/lib/useBaseQuery.d.ts +0 -3
- package/build/lib/useBaseQuery.esm.js +0 -63
- package/build/lib/useBaseQuery.esm.js.map +0 -1
- package/build/lib/useBaseQuery.js +0 -84
- package/build/lib/useBaseQuery.js.map +0 -1
- package/build/lib/useBaseQuery.mjs +0 -63
- package/build/lib/useBaseQuery.mjs.map +0 -1
- package/build/lib/useInfiniteQuery.d.ts +0 -3
- package/build/lib/useInfiniteQuery.esm.js +0 -13
- package/build/lib/useInfiniteQuery.esm.js.map +0 -1
- package/build/lib/useInfiniteQuery.js +0 -15
- package/build/lib/useInfiniteQuery.js.map +0 -1
- package/build/lib/useInfiniteQuery.mjs +0 -13
- package/build/lib/useInfiniteQuery.mjs.map +0 -1
- package/build/lib/useIsFetching.d.ts +0 -2
- package/build/lib/useIsFetching.esm.js +0 -13
- package/build/lib/useIsFetching.esm.js.map +0 -1
- package/build/lib/useIsFetching.js +0 -34
- package/build/lib/useIsFetching.js.map +0 -1
- package/build/lib/useIsFetching.mjs +0 -13
- package/build/lib/useIsFetching.mjs.map +0 -1
- package/build/lib/useMutation.d.ts +0 -3
- package/build/lib/useMutation.esm.js +0 -33
- package/build/lib/useMutation.esm.js.map +0 -1
- package/build/lib/useMutation.js +0 -54
- package/build/lib/useMutation.js.map +0 -1
- package/build/lib/useMutation.mjs +0 -33
- package/build/lib/useMutation.mjs.map +0 -1
- package/build/lib/useMutationState.d.ts +0 -8
- package/build/lib/useMutationState.esm.js +0 -38
- package/build/lib/useMutationState.esm.js.map +0 -1
- package/build/lib/useMutationState.js +0 -60
- package/build/lib/useMutationState.js.map +0 -1
- package/build/lib/useMutationState.mjs +0 -38
- package/build/lib/useMutationState.mjs.map +0 -1
- package/build/lib/useQueries.esm.js +0 -73
- package/build/lib/useQueries.esm.js.map +0 -1
- package/build/lib/useQueries.js +0 -94
- package/build/lib/useQueries.js.map +0 -1
- package/build/lib/useQueries.mjs +0 -70
- package/build/lib/useQueries.mjs.map +0 -1
- package/build/lib/useQuery.d.ts +0 -11
- package/build/lib/useQuery.esm.js +0 -12
- package/build/lib/useQuery.esm.js.map +0 -1
- package/build/lib/useQuery.js +0 -14
- package/build/lib/useQuery.js.map +0 -1
- package/build/lib/useQuery.mjs +0 -12
- package/build/lib/useQuery.mjs.map +0 -1
- package/build/lib/utils.d.ts +0 -1
- package/build/lib/utils.esm.js +0 -10
- package/build/lib/utils.esm.js.map +0 -1
- package/build/lib/utils.js +0 -12
- package/build/lib/utils.js.map +0 -1
- package/build/lib/utils.mjs +0 -10
- package/build/lib/utils.mjs.map +0 -1
- package/build/umd/index.development.js +0 -3040
- package/build/umd/index.development.js.map +0 -1
- package/build/umd/index.production.js +0 -2
- package/build/umd/index.production.js.map +0 -1
- /package/src/{isRestoring.tsx → isRestoring.ts} +0 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { act, fireEvent, render, waitFor } from '@testing-library/react'
|
|
2
2
|
import '@testing-library/jest-dom'
|
|
3
3
|
import * as React from 'react'
|
|
4
|
+
import { ErrorBoundary } from 'react-error-boundary'
|
|
5
|
+
import { vi } from 'vitest'
|
|
6
|
+
import { QueryCache, keepPreviousData, useQuery } from '..'
|
|
4
7
|
import {
|
|
5
8
|
Blink,
|
|
6
9
|
createQueryClient,
|
|
7
10
|
expectType,
|
|
8
|
-
|
|
11
|
+
mockOnlineManagerIsOnline,
|
|
9
12
|
mockVisibilityState,
|
|
10
13
|
queryKey,
|
|
11
14
|
renderWithClient,
|
|
@@ -15,13 +18,9 @@ import {
|
|
|
15
18
|
import type {
|
|
16
19
|
DefinedUseQueryResult,
|
|
17
20
|
QueryFunction,
|
|
18
|
-
QueryFunctionContext,
|
|
19
21
|
UseQueryOptions,
|
|
20
22
|
UseQueryResult,
|
|
21
23
|
} from '..'
|
|
22
|
-
import { QueryCache, useQuery, keepPreviousData } from '..'
|
|
23
|
-
import { ErrorBoundary } from 'react-error-boundary'
|
|
24
|
-
import { vi } from 'vitest'
|
|
25
24
|
import type { Mock } from 'vitest'
|
|
26
25
|
|
|
27
26
|
describe('useQuery', () => {
|
|
@@ -64,23 +63,17 @@ describe('useQuery', () => {
|
|
|
64
63
|
useQuery({
|
|
65
64
|
queryKey: [key],
|
|
66
65
|
queryFn: async () => true,
|
|
67
|
-
onSuccess: (data) => expectType<boolean>(data),
|
|
68
|
-
onSettled: (data) => expectType<boolean | undefined>(data),
|
|
69
66
|
})
|
|
70
67
|
|
|
71
68
|
// it should be possible to specify a union type as result type
|
|
72
69
|
const unionTypeSync = useQuery({
|
|
73
70
|
queryKey: key,
|
|
74
71
|
queryFn: () => (Math.random() > 0.5 ? 'a' : 'b'),
|
|
75
|
-
|
|
76
|
-
onSuccess: (data) => expectType<'a' | 'b'>(data),
|
|
77
72
|
})
|
|
78
73
|
expectType<'a' | 'b' | undefined>(unionTypeSync.data)
|
|
79
74
|
const unionTypeAsync = useQuery<'a' | 'b'>({
|
|
80
75
|
queryKey: key,
|
|
81
76
|
queryFn: () => Promise.resolve(Math.random() > 0.5 ? 'a' : 'b'),
|
|
82
|
-
|
|
83
|
-
onSuccess: (data) => expectType<'a' | 'b'>(data),
|
|
84
77
|
})
|
|
85
78
|
expectType<'a' | 'b' | undefined>(unionTypeAsync.data)
|
|
86
79
|
|
|
@@ -450,255 +443,6 @@ describe('useQuery', () => {
|
|
|
450
443
|
})
|
|
451
444
|
})
|
|
452
445
|
|
|
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
446
|
it('should not cancel an ongoing fetch when refetch is called with cancelRefetch=false if we have data already', async () => {
|
|
703
447
|
const key = queryKey()
|
|
704
448
|
let fetchCount = 0
|
|
@@ -948,17 +692,15 @@ describe('useQuery', () => {
|
|
|
948
692
|
// required to make sure no additional renders are happening after data is successfully fetched for the second time
|
|
949
693
|
await sleep(100)
|
|
950
694
|
|
|
951
|
-
expect(states.length).toBe(
|
|
695
|
+
expect(states.length).toBe(4)
|
|
952
696
|
// First load
|
|
953
697
|
expect(states[0]).toMatchObject({ isPending: true, isSuccess: false })
|
|
954
698
|
// First success
|
|
955
699
|
expect(states[1]).toMatchObject({ isPending: false, isSuccess: true })
|
|
956
700
|
// Remove
|
|
957
701
|
expect(states[2]).toMatchObject({ isPending: true, isSuccess: false })
|
|
958
|
-
// Hook state update
|
|
959
|
-
expect(states[3]).toMatchObject({ isPending: true, isSuccess: false })
|
|
960
702
|
// Second success
|
|
961
|
-
expect(states[
|
|
703
|
+
expect(states[3]).toMatchObject({ isPending: false, isSuccess: true })
|
|
962
704
|
})
|
|
963
705
|
|
|
964
706
|
it('should fetch when refetchOnMount is false and nothing has been fetched yet', async () => {
|
|
@@ -1060,48 +802,6 @@ describe('useQuery', () => {
|
|
|
1060
802
|
expect(states[1]).toMatchObject({ data: 'test' })
|
|
1061
803
|
})
|
|
1062
804
|
|
|
1063
|
-
it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {
|
|
1064
|
-
const key = queryKey()
|
|
1065
|
-
const states: UseQueryResult<string>[] = []
|
|
1066
|
-
|
|
1067
|
-
function Page() {
|
|
1068
|
-
const state = useQuery({
|
|
1069
|
-
queryKey: key,
|
|
1070
|
-
queryFn: () => ({ name: 'test' }),
|
|
1071
|
-
select: (data) => data.name,
|
|
1072
|
-
notifyOnChangeProps: ['data'],
|
|
1073
|
-
})
|
|
1074
|
-
|
|
1075
|
-
states.push(state)
|
|
1076
|
-
|
|
1077
|
-
return (
|
|
1078
|
-
<div>
|
|
1079
|
-
<div>{state.data}</div>
|
|
1080
|
-
<button onClick={() => state.refetch()}>refetch</button>
|
|
1081
|
-
</div>
|
|
1082
|
-
)
|
|
1083
|
-
}
|
|
1084
|
-
|
|
1085
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
1086
|
-
|
|
1087
|
-
await waitFor(() => {
|
|
1088
|
-
rendered.getByText('test')
|
|
1089
|
-
})
|
|
1090
|
-
|
|
1091
|
-
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
1092
|
-
|
|
1093
|
-
await waitFor(() => {
|
|
1094
|
-
rendered.getByText('test')
|
|
1095
|
-
})
|
|
1096
|
-
|
|
1097
|
-
expect(states[0]).toMatchObject({ data: undefined })
|
|
1098
|
-
expect(states[1]).toMatchObject({ data: 'test' })
|
|
1099
|
-
|
|
1100
|
-
// make sure no additional renders happen
|
|
1101
|
-
await sleep(50)
|
|
1102
|
-
expect(states.length).toBe(2)
|
|
1103
|
-
})
|
|
1104
|
-
|
|
1105
805
|
it('should throw an error when a selector throws', async () => {
|
|
1106
806
|
const key = queryKey()
|
|
1107
807
|
const states: UseQueryResult<string>[] = []
|
|
@@ -1728,21 +1428,24 @@ describe('useQuery', () => {
|
|
|
1728
1428
|
})
|
|
1729
1429
|
})
|
|
1730
1430
|
|
|
1731
|
-
it('should
|
|
1431
|
+
it('should keep the previous data when placeholderData is set and select fn transform is used', async () => {
|
|
1732
1432
|
const key = queryKey()
|
|
1733
1433
|
const states: UseQueryResult<number>[] = []
|
|
1734
1434
|
|
|
1735
|
-
function Page(
|
|
1736
|
-
const
|
|
1435
|
+
function Page() {
|
|
1436
|
+
const [count, setCount] = React.useState(0)
|
|
1437
|
+
|
|
1438
|
+
const state = useQuery({
|
|
1737
1439
|
queryKey: [key, count],
|
|
1738
1440
|
queryFn: async () => {
|
|
1739
1441
|
await sleep(10)
|
|
1740
|
-
|
|
1741
|
-
|
|
1442
|
+
return {
|
|
1443
|
+
count,
|
|
1742
1444
|
}
|
|
1743
|
-
return Promise.resolve(count)
|
|
1744
1445
|
},
|
|
1745
|
-
|
|
1446
|
+
select(data) {
|
|
1447
|
+
return data.count
|
|
1448
|
+
},
|
|
1746
1449
|
placeholderData: keepPreviousData,
|
|
1747
1450
|
})
|
|
1748
1451
|
|
|
@@ -1750,71 +1453,259 @@ describe('useQuery', () => {
|
|
|
1750
1453
|
|
|
1751
1454
|
return (
|
|
1752
1455
|
<div>
|
|
1753
|
-
<
|
|
1754
|
-
<
|
|
1755
|
-
<p>placeholder data: {state.isPlaceholderData}</p>
|
|
1456
|
+
<div>data: {state.data}</div>
|
|
1457
|
+
<button onClick={() => setCount(1)}>setCount</button>
|
|
1756
1458
|
</div>
|
|
1757
1459
|
)
|
|
1758
1460
|
}
|
|
1759
1461
|
|
|
1760
|
-
const rendered = renderWithClient(queryClient, <Page
|
|
1462
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
1463
|
+
|
|
1761
1464
|
await waitFor(() => rendered.getByText('data: 0'))
|
|
1762
|
-
act(() => rendered.rerender(<Page count={1} />))
|
|
1763
|
-
await waitFor(() => rendered.getByText('data: 1'))
|
|
1764
|
-
act(() => rendered.rerender(<Page count={2} />))
|
|
1765
|
-
await waitFor(() => rendered.getByText('error: Error test'))
|
|
1766
1465
|
|
|
1767
|
-
|
|
1768
|
-
|
|
1466
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1467
|
+
|
|
1468
|
+
await waitFor(() => rendered.getByText('data: 1'))
|
|
1469
|
+
|
|
1470
|
+
// Initial
|
|
1769
1471
|
expect(states[0]).toMatchObject({
|
|
1770
1472
|
data: undefined,
|
|
1771
1473
|
isFetching: true,
|
|
1772
|
-
|
|
1773
|
-
error: null,
|
|
1474
|
+
isSuccess: false,
|
|
1774
1475
|
isPlaceholderData: false,
|
|
1775
1476
|
})
|
|
1776
1477
|
// Fetched
|
|
1777
1478
|
expect(states[1]).toMatchObject({
|
|
1778
1479
|
data: 0,
|
|
1779
1480
|
isFetching: false,
|
|
1780
|
-
|
|
1781
|
-
error: null,
|
|
1481
|
+
isSuccess: true,
|
|
1782
1482
|
isPlaceholderData: false,
|
|
1783
1483
|
})
|
|
1784
|
-
//
|
|
1484
|
+
// Set state
|
|
1785
1485
|
expect(states[2]).toMatchObject({
|
|
1786
1486
|
data: 0,
|
|
1787
1487
|
isFetching: true,
|
|
1788
|
-
|
|
1789
|
-
|
|
1488
|
+
isSuccess: true,
|
|
1489
|
+
isPlaceholderData: true,
|
|
1490
|
+
})
|
|
1491
|
+
// New data
|
|
1492
|
+
expect(states[3]).toMatchObject({
|
|
1493
|
+
data: 1,
|
|
1494
|
+
isFetching: false,
|
|
1495
|
+
isSuccess: true,
|
|
1496
|
+
isPlaceholderData: false,
|
|
1497
|
+
})
|
|
1498
|
+
})
|
|
1499
|
+
|
|
1500
|
+
it('should keep the previous queryKey (from prevQuery) between multiple pending queries when placeholderData is set and select fn transform is used', async () => {
|
|
1501
|
+
const keys: Array<readonly unknown[] | null> = []
|
|
1502
|
+
const key = queryKey()
|
|
1503
|
+
const states: UseQueryResult<number>[] = []
|
|
1504
|
+
|
|
1505
|
+
function Page() {
|
|
1506
|
+
const [count, setCount] = React.useState(0)
|
|
1507
|
+
|
|
1508
|
+
const state = useQuery({
|
|
1509
|
+
queryKey: [key, count],
|
|
1510
|
+
queryFn: async () => {
|
|
1511
|
+
await sleep(10)
|
|
1512
|
+
return {
|
|
1513
|
+
count,
|
|
1514
|
+
}
|
|
1515
|
+
},
|
|
1516
|
+
select(data) {
|
|
1517
|
+
return data.count
|
|
1518
|
+
},
|
|
1519
|
+
placeholderData: (prevData, prevQuery) => {
|
|
1520
|
+
if (prevQuery) {
|
|
1521
|
+
keys.push(prevQuery.queryKey)
|
|
1522
|
+
}
|
|
1523
|
+
return prevData
|
|
1524
|
+
},
|
|
1525
|
+
})
|
|
1526
|
+
|
|
1527
|
+
states.push(state)
|
|
1528
|
+
|
|
1529
|
+
return (
|
|
1530
|
+
<div>
|
|
1531
|
+
<div>data: {state.data}</div>
|
|
1532
|
+
<button onClick={() => setCount((prev) => prev + 1)}>setCount</button>
|
|
1533
|
+
</div>
|
|
1534
|
+
)
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
1538
|
+
|
|
1539
|
+
await waitFor(() => rendered.getByText('data: 0'))
|
|
1540
|
+
|
|
1541
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1542
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1543
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1544
|
+
|
|
1545
|
+
await waitFor(() => rendered.getByText('data: 3'))
|
|
1546
|
+
|
|
1547
|
+
const allPreviousKeysAreTheFirstQueryKey = keys.every(
|
|
1548
|
+
(k) => JSON.stringify(k) === JSON.stringify([key, 0]),
|
|
1549
|
+
)
|
|
1550
|
+
|
|
1551
|
+
expect(allPreviousKeysAreTheFirstQueryKey).toBe(true)
|
|
1552
|
+
})
|
|
1553
|
+
|
|
1554
|
+
it('should show placeholderData between multiple pending queries when select fn transform is used', async () => {
|
|
1555
|
+
const key = queryKey()
|
|
1556
|
+
const states: UseQueryResult<number>[] = []
|
|
1557
|
+
|
|
1558
|
+
function Page() {
|
|
1559
|
+
const [count, setCount] = React.useState(0)
|
|
1560
|
+
|
|
1561
|
+
const state = useQuery({
|
|
1562
|
+
queryKey: [key, count],
|
|
1563
|
+
queryFn: async () => {
|
|
1564
|
+
await sleep(10)
|
|
1565
|
+
return {
|
|
1566
|
+
count,
|
|
1567
|
+
}
|
|
1568
|
+
},
|
|
1569
|
+
select(data) {
|
|
1570
|
+
return data.count
|
|
1571
|
+
},
|
|
1572
|
+
placeholderData: keepPreviousData,
|
|
1573
|
+
})
|
|
1574
|
+
|
|
1575
|
+
states.push(state)
|
|
1576
|
+
|
|
1577
|
+
return (
|
|
1578
|
+
<div>
|
|
1579
|
+
<div>data: {state.data}</div>
|
|
1580
|
+
<button onClick={() => setCount((prev) => prev + 1)}>setCount</button>
|
|
1581
|
+
</div>
|
|
1582
|
+
)
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
1586
|
+
|
|
1587
|
+
await waitFor(() => rendered.getByText('data: 0'))
|
|
1588
|
+
|
|
1589
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1590
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1591
|
+
fireEvent.click(rendered.getByRole('button', { name: 'setCount' }))
|
|
1592
|
+
|
|
1593
|
+
await waitFor(() => rendered.getByText('data: 3'))
|
|
1594
|
+
// Initial
|
|
1595
|
+
expect(states[0]).toMatchObject({
|
|
1596
|
+
data: undefined,
|
|
1597
|
+
isFetching: true,
|
|
1598
|
+
isSuccess: false,
|
|
1599
|
+
isPlaceholderData: false,
|
|
1600
|
+
})
|
|
1601
|
+
// Fetched
|
|
1602
|
+
expect(states[1]).toMatchObject({
|
|
1603
|
+
data: 0,
|
|
1604
|
+
isFetching: false,
|
|
1605
|
+
isSuccess: true,
|
|
1606
|
+
isPlaceholderData: false,
|
|
1607
|
+
})
|
|
1608
|
+
// Set state -> count = 1
|
|
1609
|
+
expect(states[2]).toMatchObject({
|
|
1610
|
+
data: 0,
|
|
1611
|
+
isFetching: true,
|
|
1612
|
+
isSuccess: true,
|
|
1790
1613
|
isPlaceholderData: true,
|
|
1791
1614
|
})
|
|
1792
|
-
//
|
|
1615
|
+
// Set state -> count = 2
|
|
1793
1616
|
expect(states[3]).toMatchObject({
|
|
1794
1617
|
data: 0,
|
|
1795
1618
|
isFetching: true,
|
|
1796
|
-
|
|
1797
|
-
error: null,
|
|
1619
|
+
isSuccess: true,
|
|
1798
1620
|
isPlaceholderData: true,
|
|
1799
1621
|
})
|
|
1800
|
-
//
|
|
1622
|
+
// Set state -> count = 3
|
|
1801
1623
|
expect(states[4]).toMatchObject({
|
|
1802
|
-
data:
|
|
1624
|
+
data: 0,
|
|
1625
|
+
isFetching: true,
|
|
1626
|
+
isSuccess: true,
|
|
1627
|
+
isPlaceholderData: true,
|
|
1628
|
+
})
|
|
1629
|
+
// New data
|
|
1630
|
+
expect(states[5]).toMatchObject({
|
|
1631
|
+
data: 3,
|
|
1632
|
+
isFetching: false,
|
|
1633
|
+
isSuccess: true,
|
|
1634
|
+
isPlaceholderData: false,
|
|
1635
|
+
})
|
|
1636
|
+
})
|
|
1637
|
+
|
|
1638
|
+
it('should transition to error state when placeholderData is set', async () => {
|
|
1639
|
+
const key = queryKey()
|
|
1640
|
+
const states: UseQueryResult<number>[] = []
|
|
1641
|
+
|
|
1642
|
+
function Page({ count }: { count: number }) {
|
|
1643
|
+
const state = useQuery<number, Error>({
|
|
1644
|
+
queryKey: [key, count],
|
|
1645
|
+
queryFn: async () => {
|
|
1646
|
+
await sleep(10)
|
|
1647
|
+
if (count === 2) {
|
|
1648
|
+
throw new Error('Error test')
|
|
1649
|
+
}
|
|
1650
|
+
return Promise.resolve(count)
|
|
1651
|
+
},
|
|
1652
|
+
retry: false,
|
|
1653
|
+
placeholderData: keepPreviousData,
|
|
1654
|
+
})
|
|
1655
|
+
|
|
1656
|
+
states.push(state)
|
|
1657
|
+
|
|
1658
|
+
return (
|
|
1659
|
+
<div>
|
|
1660
|
+
<h1>data: {state.data}</h1>
|
|
1661
|
+
<h2>error: {state.error?.message}</h2>
|
|
1662
|
+
<p>placeholder data: {state.isPlaceholderData}</p>
|
|
1663
|
+
</div>
|
|
1664
|
+
)
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
const rendered = renderWithClient(queryClient, <Page count={0} />)
|
|
1668
|
+
await waitFor(() => rendered.getByText('data: 0'))
|
|
1669
|
+
act(() => rendered.rerender(<Page count={1} />))
|
|
1670
|
+
await waitFor(() => rendered.getByText('data: 1'))
|
|
1671
|
+
act(() => rendered.rerender(<Page count={2} />))
|
|
1672
|
+
await waitFor(() => rendered.getByText('error: Error test'))
|
|
1673
|
+
|
|
1674
|
+
await waitFor(() => expect(states.length).toBe(6))
|
|
1675
|
+
// Initial
|
|
1676
|
+
expect(states[0]).toMatchObject({
|
|
1677
|
+
data: undefined,
|
|
1678
|
+
isFetching: true,
|
|
1679
|
+
status: 'pending',
|
|
1680
|
+
error: null,
|
|
1681
|
+
isPlaceholderData: false,
|
|
1682
|
+
})
|
|
1683
|
+
// Fetched
|
|
1684
|
+
expect(states[1]).toMatchObject({
|
|
1685
|
+
data: 0,
|
|
1803
1686
|
isFetching: false,
|
|
1804
1687
|
status: 'success',
|
|
1805
1688
|
error: null,
|
|
1806
1689
|
isPlaceholderData: false,
|
|
1807
1690
|
})
|
|
1808
|
-
// rerender Page
|
|
1809
|
-
expect(states[
|
|
1810
|
-
data:
|
|
1691
|
+
// rerender Page 1
|
|
1692
|
+
expect(states[2]).toMatchObject({
|
|
1693
|
+
data: 0,
|
|
1811
1694
|
isFetching: true,
|
|
1812
1695
|
status: 'success',
|
|
1813
1696
|
error: null,
|
|
1814
1697
|
isPlaceholderData: true,
|
|
1815
1698
|
})
|
|
1816
|
-
//
|
|
1817
|
-
expect(states[
|
|
1699
|
+
// New data
|
|
1700
|
+
expect(states[3]).toMatchObject({
|
|
1701
|
+
data: 1,
|
|
1702
|
+
isFetching: false,
|
|
1703
|
+
status: 'success',
|
|
1704
|
+
error: null,
|
|
1705
|
+
isPlaceholderData: false,
|
|
1706
|
+
})
|
|
1707
|
+
// rerender Page 2
|
|
1708
|
+
expect(states[4]).toMatchObject({
|
|
1818
1709
|
data: 1,
|
|
1819
1710
|
isFetching: true,
|
|
1820
1711
|
status: 'success',
|
|
@@ -1822,13 +1713,13 @@ describe('useQuery', () => {
|
|
|
1822
1713
|
isPlaceholderData: true,
|
|
1823
1714
|
})
|
|
1824
1715
|
// Error
|
|
1825
|
-
expect(states[
|
|
1716
|
+
expect(states[5]).toMatchObject({
|
|
1826
1717
|
data: undefined,
|
|
1827
1718
|
isFetching: false,
|
|
1828
1719
|
status: 'error',
|
|
1829
1720
|
isPlaceholderData: false,
|
|
1830
1721
|
})
|
|
1831
|
-
expect(states[
|
|
1722
|
+
expect(states[5]!.error).toHaveProperty('message', 'Error test')
|
|
1832
1723
|
})
|
|
1833
1724
|
|
|
1834
1725
|
it('should not show initial data from next query if placeholderData is set', async () => {
|
|
@@ -1873,7 +1764,7 @@ describe('useQuery', () => {
|
|
|
1873
1764
|
rendered.getByText('data: 1, count: 1, isFetching: false'),
|
|
1874
1765
|
)
|
|
1875
1766
|
|
|
1876
|
-
expect(states.length).toBe(
|
|
1767
|
+
expect(states.length).toBe(4)
|
|
1877
1768
|
|
|
1878
1769
|
// Initial
|
|
1879
1770
|
expect(states[0]).toMatchObject({
|
|
@@ -1896,15 +1787,8 @@ describe('useQuery', () => {
|
|
|
1896
1787
|
isSuccess: true,
|
|
1897
1788
|
isPlaceholderData: false,
|
|
1898
1789
|
})
|
|
1899
|
-
// Hook state update
|
|
1900
|
-
expect(states[3]).toMatchObject({
|
|
1901
|
-
data: 99,
|
|
1902
|
-
isFetching: true,
|
|
1903
|
-
isSuccess: true,
|
|
1904
|
-
isPlaceholderData: false,
|
|
1905
|
-
})
|
|
1906
1790
|
// New data
|
|
1907
|
-
expect(states[
|
|
1791
|
+
expect(states[3]).toMatchObject({
|
|
1908
1792
|
data: 1,
|
|
1909
1793
|
isFetching: false,
|
|
1910
1794
|
isSuccess: true,
|
|
@@ -2276,67 +2160,271 @@ describe('useQuery', () => {
|
|
|
2276
2160
|
|
|
2277
2161
|
renderWithClient(queryClient, <Page />)
|
|
2278
2162
|
|
|
2279
|
-
await sleep(100)
|
|
2163
|
+
await sleep(100)
|
|
2164
|
+
|
|
2165
|
+
expect(states.length).toBe(3)
|
|
2166
|
+
expect(states[0]).toMatchObject({ isStale: true })
|
|
2167
|
+
expect(states[1]).toMatchObject({ isStale: false })
|
|
2168
|
+
expect(states[2]).toMatchObject({ isStale: true })
|
|
2169
|
+
})
|
|
2170
|
+
|
|
2171
|
+
describe('notifyOnChangeProps', () => {
|
|
2172
|
+
it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {
|
|
2173
|
+
const key = queryKey()
|
|
2174
|
+
const states: UseQueryResult<string>[] = []
|
|
2175
|
+
|
|
2176
|
+
function Page() {
|
|
2177
|
+
const state = useQuery({
|
|
2178
|
+
queryKey: key,
|
|
2179
|
+
queryFn: () => ({ name: 'test' }),
|
|
2180
|
+
select: (data) => data.name,
|
|
2181
|
+
notifyOnChangeProps: ['data'],
|
|
2182
|
+
})
|
|
2183
|
+
|
|
2184
|
+
states.push(state)
|
|
2185
|
+
|
|
2186
|
+
return (
|
|
2187
|
+
<div>
|
|
2188
|
+
<div>{state.data}</div>
|
|
2189
|
+
<button onClick={() => state.refetch()}>refetch</button>
|
|
2190
|
+
</div>
|
|
2191
|
+
)
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2195
|
+
|
|
2196
|
+
await waitFor(() => {
|
|
2197
|
+
rendered.getByText('test')
|
|
2198
|
+
})
|
|
2199
|
+
|
|
2200
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2201
|
+
|
|
2202
|
+
await waitFor(() => {
|
|
2203
|
+
rendered.getByText('test')
|
|
2204
|
+
})
|
|
2205
|
+
|
|
2206
|
+
expect(states[0]).toMatchObject({ data: undefined })
|
|
2207
|
+
expect(states[1]).toMatchObject({ data: 'test' })
|
|
2208
|
+
|
|
2209
|
+
// make sure no additional renders happen
|
|
2210
|
+
await sleep(50)
|
|
2211
|
+
expect(states.length).toBe(2)
|
|
2212
|
+
})
|
|
2213
|
+
it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
|
|
2214
|
+
const key = queryKey()
|
|
2215
|
+
const states: UseQueryResult<string>[] = []
|
|
2216
|
+
|
|
2217
|
+
function Page() {
|
|
2218
|
+
const state = useQuery({
|
|
2219
|
+
queryKey: key,
|
|
2220
|
+
queryFn: async () => {
|
|
2221
|
+
await sleep(5)
|
|
2222
|
+
return 'test'
|
|
2223
|
+
},
|
|
2224
|
+
|
|
2225
|
+
notifyOnChangeProps: ['data'],
|
|
2226
|
+
})
|
|
2227
|
+
|
|
2228
|
+
states.push(state)
|
|
2229
|
+
|
|
2230
|
+
return (
|
|
2231
|
+
<>
|
|
2232
|
+
<button
|
|
2233
|
+
onClick={async () => {
|
|
2234
|
+
await state.refetch()
|
|
2235
|
+
}}
|
|
2236
|
+
>
|
|
2237
|
+
refetch
|
|
2238
|
+
</button>
|
|
2239
|
+
|
|
2240
|
+
<div>{state.data}</div>
|
|
2241
|
+
</>
|
|
2242
|
+
)
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2246
|
+
|
|
2247
|
+
await waitFor(() => {
|
|
2248
|
+
rendered.getByText('test')
|
|
2249
|
+
})
|
|
2250
|
+
|
|
2251
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2252
|
+
|
|
2253
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2254
|
+
await sleep(20)
|
|
2255
|
+
|
|
2256
|
+
expect(states.length).toBe(2)
|
|
2257
|
+
expect(states[0]).toMatchObject({
|
|
2258
|
+
data: undefined,
|
|
2259
|
+
status: 'pending',
|
|
2260
|
+
isFetching: true,
|
|
2261
|
+
})
|
|
2262
|
+
expect(states[1]).toMatchObject({
|
|
2263
|
+
data: 'test',
|
|
2264
|
+
status: 'success',
|
|
2265
|
+
isFetching: false,
|
|
2266
|
+
})
|
|
2267
|
+
})
|
|
2268
|
+
|
|
2269
|
+
// See https://github.com/TanStack/query/discussions/5588
|
|
2270
|
+
describe('function', () => {
|
|
2271
|
+
it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
|
|
2272
|
+
const key = queryKey()
|
|
2273
|
+
const states: UseQueryResult<string>[] = []
|
|
2274
|
+
|
|
2275
|
+
function Page() {
|
|
2276
|
+
const state = useQuery({
|
|
2277
|
+
queryKey: key,
|
|
2278
|
+
queryFn: async () => {
|
|
2279
|
+
await sleep(5)
|
|
2280
|
+
return 'test'
|
|
2281
|
+
},
|
|
2282
|
+
notifyOnChangeProps: () => ['data'],
|
|
2283
|
+
})
|
|
2284
|
+
|
|
2285
|
+
states.push(state)
|
|
2286
|
+
|
|
2287
|
+
return (
|
|
2288
|
+
<>
|
|
2289
|
+
<button
|
|
2290
|
+
onClick={async () => {
|
|
2291
|
+
await state.refetch()
|
|
2292
|
+
}}
|
|
2293
|
+
>
|
|
2294
|
+
refetch
|
|
2295
|
+
</button>
|
|
2296
|
+
|
|
2297
|
+
<div>{state.data}</div>
|
|
2298
|
+
</>
|
|
2299
|
+
)
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2303
|
+
|
|
2304
|
+
await waitFor(() => {
|
|
2305
|
+
rendered.getByText('test')
|
|
2306
|
+
})
|
|
2307
|
+
|
|
2308
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2309
|
+
|
|
2310
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2311
|
+
await sleep(20)
|
|
2312
|
+
|
|
2313
|
+
expect(states.length).toBe(2)
|
|
2314
|
+
expect(states[0]).toMatchObject({
|
|
2315
|
+
data: undefined,
|
|
2316
|
+
status: 'pending',
|
|
2317
|
+
isFetching: true,
|
|
2318
|
+
})
|
|
2319
|
+
expect(states[1]).toMatchObject({
|
|
2320
|
+
data: 'test',
|
|
2321
|
+
status: 'success',
|
|
2322
|
+
isFetching: false,
|
|
2323
|
+
})
|
|
2324
|
+
})
|
|
2325
|
+
|
|
2326
|
+
it('should not re-render when change props are not actively being tracked', async () => {
|
|
2327
|
+
const key = queryKey()
|
|
2328
|
+
const states: UseQueryResult<string>[] = []
|
|
2280
2329
|
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
expect(states[2]).toMatchObject({ isStale: true })
|
|
2285
|
-
})
|
|
2330
|
+
function Page() {
|
|
2331
|
+
const fetchCounterRef = React.useRef(0)
|
|
2332
|
+
const trackChangesRef = React.useRef(true)
|
|
2286
2333
|
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2334
|
+
const notifyOnChangeProps = React.useCallback(() => {
|
|
2335
|
+
return trackChangesRef.current ? 'all' : []
|
|
2336
|
+
}, [])
|
|
2290
2337
|
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2338
|
+
const state = useQuery({
|
|
2339
|
+
queryKey: key,
|
|
2340
|
+
queryFn: async () => {
|
|
2341
|
+
await sleep(5)
|
|
2342
|
+
fetchCounterRef.current++
|
|
2343
|
+
return `fetch counter: ${fetchCounterRef.current}`
|
|
2344
|
+
},
|
|
2345
|
+
notifyOnChangeProps,
|
|
2346
|
+
})
|
|
2298
2347
|
|
|
2299
|
-
|
|
2300
|
-
})
|
|
2348
|
+
states.push(state)
|
|
2301
2349
|
|
|
2302
|
-
|
|
2350
|
+
return (
|
|
2351
|
+
<>
|
|
2352
|
+
<button
|
|
2353
|
+
onClick={async () => {
|
|
2354
|
+
await state.refetch()
|
|
2355
|
+
}}
|
|
2356
|
+
>
|
|
2357
|
+
refetch
|
|
2358
|
+
</button>
|
|
2359
|
+
<button
|
|
2360
|
+
onClick={() => {
|
|
2361
|
+
trackChangesRef.current = true
|
|
2362
|
+
}}
|
|
2363
|
+
>
|
|
2364
|
+
enableTracking
|
|
2365
|
+
</button>
|
|
2366
|
+
<button
|
|
2367
|
+
onClick={() => {
|
|
2368
|
+
trackChangesRef.current = false
|
|
2369
|
+
}}
|
|
2370
|
+
>
|
|
2371
|
+
disableTracking
|
|
2372
|
+
</button>
|
|
2373
|
+
|
|
2374
|
+
<div>{state.data}</div>
|
|
2375
|
+
</>
|
|
2376
|
+
)
|
|
2377
|
+
}
|
|
2303
2378
|
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
await state.refetch()
|
|
2309
|
-
}}
|
|
2310
|
-
>
|
|
2311
|
-
refetch
|
|
2312
|
-
</button>
|
|
2379
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2380
|
+
await waitFor(() => {
|
|
2381
|
+
rendered.getByText('fetch counter: 1')
|
|
2382
|
+
})
|
|
2313
2383
|
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2384
|
+
expect(states.length).toBe(2)
|
|
2385
|
+
expect(states[0]).toMatchObject({
|
|
2386
|
+
data: undefined,
|
|
2387
|
+
isFetching: true,
|
|
2388
|
+
status: 'pending',
|
|
2389
|
+
})
|
|
2390
|
+
expect(states[1]).toMatchObject({
|
|
2391
|
+
data: 'fetch counter: 1',
|
|
2392
|
+
status: 'success',
|
|
2393
|
+
isFetching: false,
|
|
2394
|
+
})
|
|
2318
2395
|
|
|
2319
|
-
|
|
2396
|
+
// disable tracking and refetch to check for re-renders
|
|
2397
|
+
fireEvent.click(
|
|
2398
|
+
rendered.getByRole('button', { name: 'disableTracking' }),
|
|
2399
|
+
)
|
|
2400
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2320
2401
|
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2402
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2403
|
+
await sleep(20)
|
|
2404
|
+
// still expect to only have two re-renders from the initial fetch
|
|
2405
|
+
expect(states.length).toBe(2)
|
|
2324
2406
|
|
|
2325
|
-
|
|
2407
|
+
// enable tracking and refetch to check for re-renders
|
|
2408
|
+
fireEvent.click(
|
|
2409
|
+
rendered.getByRole('button', { name: 'enableTracking' }),
|
|
2410
|
+
)
|
|
2411
|
+
fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
|
|
2326
2412
|
|
|
2327
|
-
|
|
2328
|
-
|
|
2413
|
+
// sleep is required to make sure no additional renders happen after click
|
|
2414
|
+
await sleep(20)
|
|
2329
2415
|
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2416
|
+
expect(states.length).toBe(4)
|
|
2417
|
+
expect(states[2]).toMatchObject({
|
|
2418
|
+
data: 'fetch counter: 2',
|
|
2419
|
+
status: 'success',
|
|
2420
|
+
isFetching: true,
|
|
2421
|
+
})
|
|
2422
|
+
expect(states[3]).toMatchObject({
|
|
2423
|
+
data: 'fetch counter: 3',
|
|
2424
|
+
status: 'success',
|
|
2425
|
+
isFetching: false,
|
|
2426
|
+
})
|
|
2427
|
+
})
|
|
2340
2428
|
})
|
|
2341
2429
|
})
|
|
2342
2430
|
|
|
@@ -2434,53 +2522,6 @@ describe('useQuery', () => {
|
|
|
2434
2522
|
expect(renders).toBe(2)
|
|
2435
2523
|
})
|
|
2436
2524
|
|
|
2437
|
-
it('should batch re-renders including hook callbacks', async () => {
|
|
2438
|
-
const key = queryKey()
|
|
2439
|
-
|
|
2440
|
-
let renders = 0
|
|
2441
|
-
let callbackCount = 0
|
|
2442
|
-
|
|
2443
|
-
const queryFn = async () => {
|
|
2444
|
-
await sleep(10)
|
|
2445
|
-
return 'data'
|
|
2446
|
-
}
|
|
2447
|
-
|
|
2448
|
-
function Page() {
|
|
2449
|
-
const [count, setCount] = React.useState(0)
|
|
2450
|
-
useQuery({
|
|
2451
|
-
queryKey: key,
|
|
2452
|
-
queryFn,
|
|
2453
|
-
onSuccess: () => {
|
|
2454
|
-
setCount((x) => x + 1)
|
|
2455
|
-
},
|
|
2456
|
-
})
|
|
2457
|
-
useQuery({
|
|
2458
|
-
queryKey: key,
|
|
2459
|
-
queryFn,
|
|
2460
|
-
onSuccess: () => {
|
|
2461
|
-
setCount((x) => x + 1)
|
|
2462
|
-
},
|
|
2463
|
-
})
|
|
2464
|
-
|
|
2465
|
-
React.useEffect(() => {
|
|
2466
|
-
renders++
|
|
2467
|
-
callbackCount = count
|
|
2468
|
-
})
|
|
2469
|
-
|
|
2470
|
-
return <div>count: {count}</div>
|
|
2471
|
-
}
|
|
2472
|
-
|
|
2473
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
2474
|
-
|
|
2475
|
-
await waitFor(() => rendered.getByText('count: 2'))
|
|
2476
|
-
|
|
2477
|
-
// Should be 3 instead of 5
|
|
2478
|
-
expect(renders).toBe(3)
|
|
2479
|
-
|
|
2480
|
-
// Both callbacks should have been executed
|
|
2481
|
-
expect(callbackCount).toBe(2)
|
|
2482
|
-
})
|
|
2483
|
-
|
|
2484
2525
|
it('should render latest data even if react has discarded certain renders', async () => {
|
|
2485
2526
|
const key = queryKey()
|
|
2486
2527
|
|
|
@@ -2557,33 +2598,6 @@ describe('useQuery', () => {
|
|
|
2557
2598
|
rendered.getByText('status: pending')
|
|
2558
2599
|
})
|
|
2559
2600
|
|
|
2560
|
-
// See https://github.com/tannerlinsley/react-query/issues/147
|
|
2561
|
-
it('should not pass stringified variables to query function', async () => {
|
|
2562
|
-
const key = queryKey()
|
|
2563
|
-
const variables = { number: 5, boolean: false, object: {}, array: [] }
|
|
2564
|
-
type CustomQueryKey = [typeof key, typeof variables]
|
|
2565
|
-
const states: UseQueryResult<CustomQueryKey>[] = []
|
|
2566
|
-
|
|
2567
|
-
const queryFn = async (ctx: QueryFunctionContext<CustomQueryKey>) => {
|
|
2568
|
-
await sleep(10)
|
|
2569
|
-
return ctx.queryKey
|
|
2570
|
-
}
|
|
2571
|
-
|
|
2572
|
-
function Page() {
|
|
2573
|
-
const state = useQuery({ queryKey: [key, variables], queryFn })
|
|
2574
|
-
states.push(state)
|
|
2575
|
-
return <div>{state.status}</div>
|
|
2576
|
-
}
|
|
2577
|
-
|
|
2578
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
2579
|
-
|
|
2580
|
-
await waitFor(() => {
|
|
2581
|
-
rendered.getByText('success')
|
|
2582
|
-
})
|
|
2583
|
-
|
|
2584
|
-
expect(states[1]?.data).toEqual([key, variables])
|
|
2585
|
-
})
|
|
2586
|
-
|
|
2587
2601
|
it('should not refetch query on focus when `enabled` is set to `false`', async () => {
|
|
2588
2602
|
const key = queryKey()
|
|
2589
2603
|
const queryFn = vi.fn<unknown[], string>().mockReturnValue('data')
|
|
@@ -2723,24 +2737,24 @@ describe('useQuery', () => {
|
|
|
2723
2737
|
refetchOnWindowFocus: 'always',
|
|
2724
2738
|
})
|
|
2725
2739
|
states.push(state)
|
|
2726
|
-
return
|
|
2740
|
+
return (
|
|
2741
|
+
<div>
|
|
2742
|
+
<div>
|
|
2743
|
+
data: {state.data}, isFetching: {String(state.isFetching)}
|
|
2744
|
+
</div>
|
|
2745
|
+
</div>
|
|
2746
|
+
)
|
|
2727
2747
|
}
|
|
2728
2748
|
|
|
2729
|
-
renderWithClient(queryClient, <Page />)
|
|
2749
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
2730
2750
|
|
|
2731
|
-
await
|
|
2751
|
+
await waitFor(() => rendered.getByText('data: 0, isFetching: false'))
|
|
2732
2752
|
|
|
2733
2753
|
act(() => {
|
|
2734
2754
|
window.dispatchEvent(new Event('visibilitychange'))
|
|
2735
2755
|
})
|
|
2736
2756
|
|
|
2737
|
-
await
|
|
2738
|
-
|
|
2739
|
-
await waitFor(() => expect(states.length).toBe(4))
|
|
2740
|
-
expect(states[0]).toMatchObject({ data: undefined, isFetching: true })
|
|
2741
|
-
expect(states[1]).toMatchObject({ data: 0, isFetching: false })
|
|
2742
|
-
expect(states[2]).toMatchObject({ data: 0, isFetching: true })
|
|
2743
|
-
expect(states[3]).toMatchObject({ data: 1, isFetching: false })
|
|
2757
|
+
await waitFor(() => rendered.getByText('data: 1, isFetching: false'))
|
|
2744
2758
|
})
|
|
2745
2759
|
|
|
2746
2760
|
it('should calculate focus behaviour for `refetchOnWindowFocus` depending on function', async () => {
|
|
@@ -2896,7 +2910,7 @@ describe('useQuery', () => {
|
|
|
2896
2910
|
await waitFor(() => rendered.getByText('Error test jaylen'))
|
|
2897
2911
|
})
|
|
2898
2912
|
|
|
2899
|
-
it('should throw error if queryFn throws and
|
|
2913
|
+
it('should throw error if queryFn throws and throwOnError is in use', async () => {
|
|
2900
2914
|
const consoleMock = vi
|
|
2901
2915
|
.spyOn(console, 'error')
|
|
2902
2916
|
.mockImplementation(() => undefined)
|
|
@@ -2907,7 +2921,7 @@ describe('useQuery', () => {
|
|
|
2907
2921
|
queryKey: key,
|
|
2908
2922
|
queryFn: () => Promise.reject(new Error('Error test jaylen')),
|
|
2909
2923
|
retry: false,
|
|
2910
|
-
|
|
2924
|
+
throwOnError: true,
|
|
2911
2925
|
})
|
|
2912
2926
|
|
|
2913
2927
|
return (
|
|
@@ -2929,7 +2943,7 @@ describe('useQuery', () => {
|
|
|
2929
2943
|
consoleMock.mockRestore()
|
|
2930
2944
|
})
|
|
2931
2945
|
|
|
2932
|
-
it('should update with data if we observe no properties and
|
|
2946
|
+
it('should update with data if we observe no properties and throwOnError', async () => {
|
|
2933
2947
|
const key = queryKey()
|
|
2934
2948
|
|
|
2935
2949
|
let result: UseQueryResult<string> | undefined
|
|
@@ -2938,7 +2952,7 @@ describe('useQuery', () => {
|
|
|
2938
2952
|
const query = useQuery({
|
|
2939
2953
|
queryKey: key,
|
|
2940
2954
|
queryFn: () => Promise.resolve('data'),
|
|
2941
|
-
|
|
2955
|
+
throwOnError: true,
|
|
2942
2956
|
})
|
|
2943
2957
|
|
|
2944
2958
|
React.useEffect(() => {
|
|
@@ -2966,7 +2980,7 @@ describe('useQuery', () => {
|
|
|
2966
2980
|
queryFn: () => Promise.reject(new Error('Local Error')),
|
|
2967
2981
|
|
|
2968
2982
|
retry: false,
|
|
2969
|
-
|
|
2983
|
+
throwOnError: (err) => err.message !== 'Local Error',
|
|
2970
2984
|
})
|
|
2971
2985
|
|
|
2972
2986
|
return (
|
|
@@ -3001,7 +3015,7 @@ describe('useQuery', () => {
|
|
|
3001
3015
|
queryFn: () => Promise.reject(new Error('Remote Error')),
|
|
3002
3016
|
|
|
3003
3017
|
retry: false,
|
|
3004
|
-
|
|
3018
|
+
throwOnError: (err) => err.message !== 'Local Error',
|
|
3005
3019
|
})
|
|
3006
3020
|
|
|
3007
3021
|
return (
|
|
@@ -3758,6 +3772,7 @@ describe('useQuery', () => {
|
|
|
3758
3772
|
})
|
|
3759
3773
|
act(() => setPrefetched(true))
|
|
3760
3774
|
}
|
|
3775
|
+
|
|
3761
3776
|
prefetch()
|
|
3762
3777
|
}, [])
|
|
3763
3778
|
|
|
@@ -5200,7 +5215,7 @@ describe('useQuery', () => {
|
|
|
5200
5215
|
|
|
5201
5216
|
describe('networkMode online', () => {
|
|
5202
5217
|
it('online queries should not start fetching if you are offline', async () => {
|
|
5203
|
-
const onlineMock =
|
|
5218
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5204
5219
|
|
|
5205
5220
|
const key = queryKey()
|
|
5206
5221
|
const states: Array<any> = []
|
|
@@ -5229,10 +5244,11 @@ describe('useQuery', () => {
|
|
|
5229
5244
|
}
|
|
5230
5245
|
|
|
5231
5246
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5247
|
+
window.dispatchEvent(new Event('offline'))
|
|
5232
5248
|
|
|
5233
5249
|
await waitFor(() => rendered.getByText('status: pending, isPaused: true'))
|
|
5234
5250
|
|
|
5235
|
-
onlineMock.
|
|
5251
|
+
onlineMock.mockRestore()
|
|
5236
5252
|
window.dispatchEvent(new Event('online'))
|
|
5237
5253
|
|
|
5238
5254
|
await waitFor(() =>
|
|
@@ -5243,8 +5259,6 @@ describe('useQuery', () => {
|
|
|
5243
5259
|
})
|
|
5244
5260
|
|
|
5245
5261
|
expect(states).toEqual(['paused', 'fetching', 'idle'])
|
|
5246
|
-
|
|
5247
|
-
onlineMock.mockRestore()
|
|
5248
5262
|
})
|
|
5249
5263
|
|
|
5250
5264
|
it('online queries should not refetch if you are offline', async () => {
|
|
@@ -5282,7 +5296,9 @@ describe('useQuery', () => {
|
|
|
5282
5296
|
|
|
5283
5297
|
await waitFor(() => rendered.getByText('data: data1'))
|
|
5284
5298
|
|
|
5285
|
-
const onlineMock =
|
|
5299
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5300
|
+
window.dispatchEvent(new Event('offline'))
|
|
5301
|
+
|
|
5286
5302
|
fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))
|
|
5287
5303
|
|
|
5288
5304
|
await waitFor(() =>
|
|
@@ -5292,7 +5308,7 @@ describe('useQuery', () => {
|
|
|
5292
5308
|
)
|
|
5293
5309
|
await waitFor(() => rendered.getByText('failureReason: null'))
|
|
5294
5310
|
|
|
5295
|
-
onlineMock.
|
|
5311
|
+
onlineMock.mockRestore()
|
|
5296
5312
|
window.dispatchEvent(new Event('online'))
|
|
5297
5313
|
|
|
5298
5314
|
await waitFor(() =>
|
|
@@ -5311,8 +5327,6 @@ describe('useQuery', () => {
|
|
|
5311
5327
|
await waitFor(() => {
|
|
5312
5328
|
expect(rendered.getByText('data: data2')).toBeInTheDocument()
|
|
5313
5329
|
})
|
|
5314
|
-
|
|
5315
|
-
onlineMock.mockRestore()
|
|
5316
5330
|
})
|
|
5317
5331
|
|
|
5318
5332
|
it('online queries should not refetch if you are offline and refocus', async () => {
|
|
@@ -5348,7 +5362,7 @@ describe('useQuery', () => {
|
|
|
5348
5362
|
|
|
5349
5363
|
await waitFor(() => rendered.getByText('data: data1'))
|
|
5350
5364
|
|
|
5351
|
-
const onlineMock =
|
|
5365
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5352
5366
|
fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))
|
|
5353
5367
|
|
|
5354
5368
|
await waitFor(() =>
|
|
@@ -5394,7 +5408,7 @@ describe('useQuery', () => {
|
|
|
5394
5408
|
)
|
|
5395
5409
|
}
|
|
5396
5410
|
|
|
5397
|
-
const onlineMock =
|
|
5411
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5398
5412
|
|
|
5399
5413
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5400
5414
|
|
|
@@ -5445,7 +5459,7 @@ describe('useQuery', () => {
|
|
|
5445
5459
|
)
|
|
5446
5460
|
}
|
|
5447
5461
|
|
|
5448
|
-
const onlineMock =
|
|
5462
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5449
5463
|
|
|
5450
5464
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5451
5465
|
|
|
@@ -5499,9 +5513,10 @@ describe('useQuery', () => {
|
|
|
5499
5513
|
)
|
|
5500
5514
|
}
|
|
5501
5515
|
|
|
5502
|
-
const onlineMock =
|
|
5516
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5503
5517
|
|
|
5504
5518
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5519
|
+
window.dispatchEvent(new Event('offline'))
|
|
5505
5520
|
|
|
5506
5521
|
await waitFor(() =>
|
|
5507
5522
|
rendered.getByText('status: success, fetchStatus: paused'),
|
|
@@ -5524,7 +5539,7 @@ describe('useQuery', () => {
|
|
|
5524
5539
|
window.dispatchEvent(new Event('visibilitychange'))
|
|
5525
5540
|
})
|
|
5526
5541
|
|
|
5527
|
-
onlineMock.
|
|
5542
|
+
onlineMock.mockRestore()
|
|
5528
5543
|
act(() => {
|
|
5529
5544
|
window.dispatchEvent(new Event('online'))
|
|
5530
5545
|
})
|
|
@@ -5537,7 +5552,6 @@ describe('useQuery', () => {
|
|
|
5537
5552
|
})
|
|
5538
5553
|
|
|
5539
5554
|
expect(count).toBe(1)
|
|
5540
|
-
onlineMock.mockRestore()
|
|
5541
5555
|
})
|
|
5542
5556
|
|
|
5543
5557
|
it('online queries should pause retries if you are offline', async () => {
|
|
@@ -5570,13 +5584,11 @@ describe('useQuery', () => {
|
|
|
5570
5584
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5571
5585
|
|
|
5572
5586
|
await waitFor(() =>
|
|
5573
|
-
rendered.getByText(
|
|
5574
|
-
'status: pending, fetchStatus: fetching, failureCount: 1',
|
|
5575
|
-
),
|
|
5587
|
+
rendered.getByText(/status: pending, fetchStatus: fetching/i),
|
|
5576
5588
|
)
|
|
5577
|
-
await waitFor(() => rendered.getByText('failureReason: failed1'))
|
|
5578
5589
|
|
|
5579
|
-
const onlineMock =
|
|
5590
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5591
|
+
window.dispatchEvent(new Event('offline'))
|
|
5580
5592
|
|
|
5581
5593
|
await sleep(20)
|
|
5582
5594
|
|
|
@@ -5637,17 +5649,19 @@ describe('useQuery', () => {
|
|
|
5637
5649
|
)
|
|
5638
5650
|
}
|
|
5639
5651
|
|
|
5640
|
-
const onlineMock =
|
|
5652
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5641
5653
|
|
|
5642
5654
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5643
5655
|
|
|
5656
|
+
window.dispatchEvent(new Event('offline'))
|
|
5657
|
+
|
|
5644
5658
|
await waitFor(() =>
|
|
5645
5659
|
rendered.getByText('status: pending, fetchStatus: paused'),
|
|
5646
5660
|
)
|
|
5647
5661
|
|
|
5648
5662
|
fireEvent.click(rendered.getByRole('button', { name: /hide/i }))
|
|
5649
5663
|
|
|
5650
|
-
onlineMock.
|
|
5664
|
+
onlineMock.mockRestore()
|
|
5651
5665
|
window.dispatchEvent(new Event('online'))
|
|
5652
5666
|
|
|
5653
5667
|
await waitFor(() => {
|
|
@@ -5660,8 +5674,6 @@ describe('useQuery', () => {
|
|
|
5660
5674
|
// give it a bit more time to make sure queryFn is not called again
|
|
5661
5675
|
await sleep(15)
|
|
5662
5676
|
expect(count).toBe(1)
|
|
5663
|
-
|
|
5664
|
-
onlineMock.mockRestore()
|
|
5665
5677
|
})
|
|
5666
5678
|
|
|
5667
5679
|
it('online queries should not fetch if paused and we go online when cancelled and no refetchOnReconnect', async () => {
|
|
@@ -5694,7 +5706,7 @@ describe('useQuery', () => {
|
|
|
5694
5706
|
)
|
|
5695
5707
|
}
|
|
5696
5708
|
|
|
5697
|
-
const onlineMock =
|
|
5709
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5698
5710
|
|
|
5699
5711
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5700
5712
|
|
|
@@ -5770,7 +5782,7 @@ describe('useQuery', () => {
|
|
|
5770
5782
|
rendered.getByText('status: success, fetchStatus: idle'),
|
|
5771
5783
|
)
|
|
5772
5784
|
|
|
5773
|
-
const onlineMock =
|
|
5785
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5774
5786
|
|
|
5775
5787
|
fireEvent.click(rendered.getByRole('button', { name: /invalidate/i }))
|
|
5776
5788
|
|
|
@@ -5800,7 +5812,7 @@ describe('useQuery', () => {
|
|
|
5800
5812
|
|
|
5801
5813
|
describe('networkMode always', () => {
|
|
5802
5814
|
it('always queries should start fetching even if you are offline', async () => {
|
|
5803
|
-
const onlineMock =
|
|
5815
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5804
5816
|
|
|
5805
5817
|
const key = queryKey()
|
|
5806
5818
|
let count = 0
|
|
@@ -5840,7 +5852,7 @@ describe('useQuery', () => {
|
|
|
5840
5852
|
})
|
|
5841
5853
|
|
|
5842
5854
|
it('always queries should not pause retries', async () => {
|
|
5843
|
-
const onlineMock =
|
|
5855
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5844
5856
|
|
|
5845
5857
|
const key = queryKey()
|
|
5846
5858
|
let count = 0
|
|
@@ -5886,7 +5898,7 @@ describe('useQuery', () => {
|
|
|
5886
5898
|
|
|
5887
5899
|
describe('networkMode offlineFirst', () => {
|
|
5888
5900
|
it('offlineFirst queries should start fetching if you are offline, but pause retries', async () => {
|
|
5889
|
-
const onlineMock =
|
|
5901
|
+
const onlineMock = mockOnlineManagerIsOnline(false)
|
|
5890
5902
|
|
|
5891
5903
|
const key = queryKey()
|
|
5892
5904
|
let count = 0
|
|
@@ -5917,6 +5929,8 @@ describe('useQuery', () => {
|
|
|
5917
5929
|
|
|
5918
5930
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
5919
5931
|
|
|
5932
|
+
window.dispatchEvent(new Event('offline'))
|
|
5933
|
+
|
|
5920
5934
|
await waitFor(() =>
|
|
5921
5935
|
rendered.getByText(
|
|
5922
5936
|
'status: pending, fetchStatus: paused, failureCount: 1',
|
|
@@ -5926,7 +5940,7 @@ describe('useQuery', () => {
|
|
|
5926
5940
|
|
|
5927
5941
|
expect(count).toBe(1)
|
|
5928
5942
|
|
|
5929
|
-
onlineMock.
|
|
5943
|
+
onlineMock.mockRestore()
|
|
5930
5944
|
window.dispatchEvent(new Event('online'))
|
|
5931
5945
|
|
|
5932
5946
|
await waitFor(() =>
|
|
@@ -5935,8 +5949,6 @@ describe('useQuery', () => {
|
|
|
5935
5949
|
await waitFor(() => rendered.getByText('failureReason: failed3'))
|
|
5936
5950
|
|
|
5937
5951
|
expect(count).toBe(3)
|
|
5938
|
-
|
|
5939
|
-
onlineMock.mockRestore()
|
|
5940
5952
|
})
|
|
5941
5953
|
})
|
|
5942
5954
|
|
|
@@ -5973,36 +5985,6 @@ describe('useQuery', () => {
|
|
|
5973
5985
|
})
|
|
5974
5986
|
})
|
|
5975
5987
|
|
|
5976
|
-
it('setQueryData - should not call onSuccess callback of active observers', async () => {
|
|
5977
|
-
const key = queryKey()
|
|
5978
|
-
const onSuccess = vi.fn()
|
|
5979
|
-
|
|
5980
|
-
function Page() {
|
|
5981
|
-
const state = useQuery({
|
|
5982
|
-
queryKey: key,
|
|
5983
|
-
queryFn: () => 'data',
|
|
5984
|
-
onSuccess,
|
|
5985
|
-
})
|
|
5986
|
-
return (
|
|
5987
|
-
<div>
|
|
5988
|
-
<div>data: {state.data}</div>
|
|
5989
|
-
<button onClick={() => queryClient.setQueryData(key, 'newData')}>
|
|
5990
|
-
setQueryData
|
|
5991
|
-
</button>
|
|
5992
|
-
</div>
|
|
5993
|
-
)
|
|
5994
|
-
}
|
|
5995
|
-
|
|
5996
|
-
const rendered = renderWithClient(queryClient, <Page />)
|
|
5997
|
-
|
|
5998
|
-
await waitFor(() => rendered.getByText('data: data'))
|
|
5999
|
-
fireEvent.click(rendered.getByRole('button', { name: /setQueryData/i }))
|
|
6000
|
-
await waitFor(() => rendered.getByText('data: newData'))
|
|
6001
|
-
|
|
6002
|
-
expect(onSuccess).toHaveBeenCalledTimes(1)
|
|
6003
|
-
expect(onSuccess).toHaveBeenCalledWith('data')
|
|
6004
|
-
})
|
|
6005
|
-
|
|
6006
5988
|
it('setQueryData - should respect updatedAt', async () => {
|
|
6007
5989
|
const key = queryKey()
|
|
6008
5990
|
|
|
@@ -6054,6 +6036,7 @@ describe('useQuery', () => {
|
|
|
6054
6036
|
</div>
|
|
6055
6037
|
)
|
|
6056
6038
|
}
|
|
6039
|
+
|
|
6057
6040
|
const rendered = renderWithClient(queryClient, <Page />)
|
|
6058
6041
|
const fetchBtn = rendered.getByRole('button', { name: 'refetch' })
|
|
6059
6042
|
await waitFor(() => rendered.getByText('data: 1'))
|
|
@@ -6085,4 +6068,161 @@ describe('useQuery', () => {
|
|
|
6085
6068
|
|
|
6086
6069
|
await waitFor(() => rendered.getByText('data: custom client'))
|
|
6087
6070
|
})
|
|
6071
|
+
|
|
6072
|
+
it('should be notified of updates between create and subscribe', async () => {
|
|
6073
|
+
const key = queryKey()
|
|
6074
|
+
|
|
6075
|
+
function Page() {
|
|
6076
|
+
const mounted = React.useRef<boolean>(false)
|
|
6077
|
+
const { data, status } = useQuery({
|
|
6078
|
+
enabled: false,
|
|
6079
|
+
queryKey: key,
|
|
6080
|
+
queryFn: async () => {
|
|
6081
|
+
await sleep(10)
|
|
6082
|
+
return 5
|
|
6083
|
+
},
|
|
6084
|
+
})
|
|
6085
|
+
|
|
6086
|
+
// this simulates a synchronous update between the time the query is created
|
|
6087
|
+
// and the time it is subscribed to that could be missed otherwise
|
|
6088
|
+
if (!mounted.current) {
|
|
6089
|
+
mounted.current = true
|
|
6090
|
+
queryClient.setQueryData(key, 1)
|
|
6091
|
+
}
|
|
6092
|
+
|
|
6093
|
+
return (
|
|
6094
|
+
<div>
|
|
6095
|
+
<span>status: {status}</span>
|
|
6096
|
+
<span>data: {data}</span>
|
|
6097
|
+
</div>
|
|
6098
|
+
)
|
|
6099
|
+
}
|
|
6100
|
+
|
|
6101
|
+
const rendered = renderWithClient(queryClient, <Page />)
|
|
6102
|
+
await waitFor(() => rendered.getByText('status: success'))
|
|
6103
|
+
await waitFor(() => rendered.getByText('data: 1'))
|
|
6104
|
+
})
|
|
6105
|
+
it('should reuse same data object reference when queryKey changes back to some cached data', async () => {
|
|
6106
|
+
const key = queryKey()
|
|
6107
|
+
const spy = vi.fn()
|
|
6108
|
+
|
|
6109
|
+
async function fetchNumber(id: number) {
|
|
6110
|
+
await sleep(5)
|
|
6111
|
+
return { numbers: { current: { id } } }
|
|
6112
|
+
}
|
|
6113
|
+
function Test() {
|
|
6114
|
+
const [id, setId] = React.useState(1)
|
|
6115
|
+
|
|
6116
|
+
const { data } = useQuery({
|
|
6117
|
+
select: selector,
|
|
6118
|
+
queryKey: [key, 'user', id],
|
|
6119
|
+
queryFn: () => fetchNumber(id),
|
|
6120
|
+
})
|
|
6121
|
+
|
|
6122
|
+
React.useEffect(() => {
|
|
6123
|
+
spy(data)
|
|
6124
|
+
}, [data])
|
|
6125
|
+
|
|
6126
|
+
return (
|
|
6127
|
+
<div>
|
|
6128
|
+
<button name="1" onClick={() => setId(1)}>
|
|
6129
|
+
1
|
|
6130
|
+
</button>
|
|
6131
|
+
<button name="2" onClick={() => setId(2)}>
|
|
6132
|
+
2
|
|
6133
|
+
</button>
|
|
6134
|
+
<span>Rendered Id: {data?.id}</span>
|
|
6135
|
+
</div>
|
|
6136
|
+
)
|
|
6137
|
+
}
|
|
6138
|
+
|
|
6139
|
+
function selector(data: any) {
|
|
6140
|
+
return data.numbers.current
|
|
6141
|
+
}
|
|
6142
|
+
|
|
6143
|
+
const rendered = renderWithClient(queryClient, <Test />)
|
|
6144
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6145
|
+
|
|
6146
|
+
spy.mockClear()
|
|
6147
|
+
await waitFor(() => rendered.getByText('Rendered Id: 1'))
|
|
6148
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6149
|
+
|
|
6150
|
+
spy.mockClear()
|
|
6151
|
+
fireEvent.click(rendered.getByRole('button', { name: /2/ }))
|
|
6152
|
+
await waitFor(() => rendered.getByText('Rendered Id: 2'))
|
|
6153
|
+
expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed
|
|
6154
|
+
|
|
6155
|
+
spy.mockClear()
|
|
6156
|
+
fireEvent.click(rendered.getByRole('button', { name: /1/ }))
|
|
6157
|
+
await waitFor(() => rendered.getByText('Rendered Id: 1'))
|
|
6158
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6159
|
+
|
|
6160
|
+
spy.mockClear()
|
|
6161
|
+
fireEvent.click(rendered.getByRole('button', { name: /2/ }))
|
|
6162
|
+
await waitFor(() => rendered.getByText('Rendered Id: 2'))
|
|
6163
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6164
|
+
})
|
|
6165
|
+
it('should reuse same data object reference when queryKey changes and placeholderData is present', async () => {
|
|
6166
|
+
const key = queryKey()
|
|
6167
|
+
const spy = vi.fn()
|
|
6168
|
+
|
|
6169
|
+
async function fetchNumber(id: number) {
|
|
6170
|
+
await sleep(5)
|
|
6171
|
+
return { numbers: { current: { id } } }
|
|
6172
|
+
}
|
|
6173
|
+
function Test() {
|
|
6174
|
+
const [id, setId] = React.useState(1)
|
|
6175
|
+
|
|
6176
|
+
const { data } = useQuery({
|
|
6177
|
+
select: selector,
|
|
6178
|
+
queryKey: [key, 'user', id],
|
|
6179
|
+
queryFn: () => fetchNumber(id),
|
|
6180
|
+
placeholderData: { numbers: { current: { id: 99 } } },
|
|
6181
|
+
})
|
|
6182
|
+
|
|
6183
|
+
React.useEffect(() => {
|
|
6184
|
+
spy(data)
|
|
6185
|
+
}, [data])
|
|
6186
|
+
|
|
6187
|
+
return (
|
|
6188
|
+
<div>
|
|
6189
|
+
<button name="1" onClick={() => setId(1)}>
|
|
6190
|
+
1
|
|
6191
|
+
</button>
|
|
6192
|
+
<button name="2" onClick={() => setId(2)}>
|
|
6193
|
+
2
|
|
6194
|
+
</button>
|
|
6195
|
+
<span>Rendered Id: {data?.id}</span>
|
|
6196
|
+
</div>
|
|
6197
|
+
)
|
|
6198
|
+
}
|
|
6199
|
+
|
|
6200
|
+
function selector(data: any) {
|
|
6201
|
+
return data.numbers.current
|
|
6202
|
+
}
|
|
6203
|
+
|
|
6204
|
+
const rendered = renderWithClient(queryClient, <Test />)
|
|
6205
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6206
|
+
|
|
6207
|
+
spy.mockClear()
|
|
6208
|
+
await waitFor(() => rendered.getByText('Rendered Id: 99'))
|
|
6209
|
+
await waitFor(() => rendered.getByText('Rendered Id: 1'))
|
|
6210
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6211
|
+
|
|
6212
|
+
spy.mockClear()
|
|
6213
|
+
fireEvent.click(rendered.getByRole('button', { name: /2/ }))
|
|
6214
|
+
await waitFor(() => rendered.getByText('Rendered Id: 99'))
|
|
6215
|
+
await waitFor(() => rendered.getByText('Rendered Id: 2'))
|
|
6216
|
+
expect(spy).toHaveBeenCalledTimes(2) // called with undefined because id changed
|
|
6217
|
+
|
|
6218
|
+
spy.mockClear()
|
|
6219
|
+
fireEvent.click(rendered.getByRole('button', { name: /1/ }))
|
|
6220
|
+
await waitFor(() => rendered.getByText('Rendered Id: 1'))
|
|
6221
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6222
|
+
|
|
6223
|
+
spy.mockClear()
|
|
6224
|
+
fireEvent.click(rendered.getByRole('button', { name: /2/ }))
|
|
6225
|
+
await waitFor(() => rendered.getByText('Rendered Id: 2'))
|
|
6226
|
+
expect(spy).toHaveBeenCalledTimes(1)
|
|
6227
|
+
})
|
|
6088
6228
|
})
|