@tanstack/react-query 4.40.2 → 4.42.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.
Files changed (114) hide show
  1. package/build/lib/Hydrate.d.ts +1 -1
  2. package/build/lib/QueryClientProvider.d.ts +1 -1
  3. package/build/lib/QueryClientProvider.esm.js.map +1 -1
  4. package/build/lib/QueryClientProvider.js.map +1 -1
  5. package/build/lib/QueryClientProvider.mjs.map +1 -1
  6. package/build/lib/QueryErrorResetBoundary.d.ts +1 -1
  7. package/build/lib/__tests__/infiniteQueryOptions.test.d.ts +2 -0
  8. package/build/lib/__tests__/infiniteQueryOptions.types.test.d.ts +2 -0
  9. package/build/lib/__tests__/useSuspenseInfiniteQuery.types.test.d.ts +2 -0
  10. package/build/lib/__tests__/utils.d.ts +2 -1
  11. package/build/lib/index.d.ts +3 -0
  12. package/build/lib/index.esm.js +2 -0
  13. package/build/lib/index.esm.js.map +1 -1
  14. package/build/lib/index.js +4 -0
  15. package/build/lib/index.js.map +1 -1
  16. package/build/lib/index.mjs +2 -0
  17. package/build/lib/index.mjs.map +1 -1
  18. package/build/lib/infiniteQueryOptions.d.ts +14 -0
  19. package/build/lib/infiniteQueryOptions.esm.js +6 -0
  20. package/build/lib/infiniteQueryOptions.esm.js.map +1 -0
  21. package/build/lib/infiniteQueryOptions.js +10 -0
  22. package/build/lib/infiniteQueryOptions.js.map +1 -0
  23. package/build/lib/infiniteQueryOptions.mjs +6 -0
  24. package/build/lib/infiniteQueryOptions.mjs.map +1 -0
  25. package/build/lib/queryOptions.d.ts +2 -2
  26. package/build/lib/queryOptions.esm.js.map +1 -1
  27. package/build/lib/queryOptions.js.map +1 -1
  28. package/build/lib/queryOptions.mjs.map +1 -1
  29. package/build/lib/suspense.esm.js +11 -0
  30. package/build/lib/suspense.esm.js.map +1 -1
  31. package/build/lib/suspense.js +11 -0
  32. package/build/lib/suspense.js.map +1 -1
  33. package/build/lib/suspense.mjs +11 -0
  34. package/build/lib/suspense.mjs.map +1 -1
  35. package/build/lib/types.d.ts +3 -1
  36. package/build/lib/useInfiniteQuery.d.ts +7 -2
  37. package/build/lib/useInfiniteQuery.esm.js.map +1 -1
  38. package/build/lib/useInfiniteQuery.js.map +1 -1
  39. package/build/lib/useInfiniteQuery.mjs.map +1 -1
  40. package/build/lib/useQuery.d.ts +6 -6
  41. package/build/lib/useQuery.esm.js.map +1 -1
  42. package/build/lib/useQuery.js.map +1 -1
  43. package/build/lib/useQuery.mjs.map +1 -1
  44. package/build/lib/useSuspenseInfiniteQuery.d.ts +5 -0
  45. package/build/lib/useSuspenseInfiniteQuery.esm.js +14 -0
  46. package/build/lib/useSuspenseInfiniteQuery.esm.js.map +1 -0
  47. package/build/lib/useSuspenseInfiniteQuery.js +18 -0
  48. package/build/lib/useSuspenseInfiniteQuery.js.map +1 -0
  49. package/build/lib/useSuspenseInfiniteQuery.mjs +14 -0
  50. package/build/lib/useSuspenseInfiniteQuery.mjs.map +1 -0
  51. package/build/umd/index.development.js +26 -0
  52. package/build/umd/index.development.js.map +1 -1
  53. package/build/umd/index.production.js +1 -1
  54. package/build/umd/index.production.js.map +1 -1
  55. package/package.json +10 -8
  56. package/src/QueryClientProvider.tsx +1 -1
  57. package/src/__tests__/infiniteQueryOptions.test.tsx +13 -0
  58. package/src/__tests__/infiniteQueryOptions.types.test.tsx +111 -0
  59. package/src/__tests__/queryOptions.types.test.tsx +8 -7
  60. package/src/__tests__/ssr-hydration.test.tsx +20 -7
  61. package/src/__tests__/suspense.test.tsx +18 -6
  62. package/src/__tests__/useMutation.test.tsx +3 -3
  63. package/src/__tests__/useQueries.test.tsx +164 -35
  64. package/src/__tests__/useQuery.test.tsx +3 -2
  65. package/src/__tests__/useSuspenseInfiniteQuery.types.test.tsx +115 -0
  66. package/src/__tests__/utils.tsx +5 -0
  67. package/src/index.ts +6 -0
  68. package/src/infiniteQueryOptions.ts +95 -0
  69. package/src/queryOptions.ts +8 -2
  70. package/src/types.ts +14 -0
  71. package/src/useInfiniteQuery.ts +28 -1
  72. package/src/useQuery.ts +6 -6
  73. package/src/useSuspenseInfiniteQuery.ts +62 -0
  74. package/build/lib/Hydrate.d.ts.map +0 -1
  75. package/build/lib/QueryClientProvider.d.ts.map +0 -1
  76. package/build/lib/QueryErrorResetBoundary.d.ts.map +0 -1
  77. package/build/lib/__tests__/Hydrate.test.d.ts.map +0 -1
  78. package/build/lib/__tests__/QueryClientProvider.test.d.ts.map +0 -1
  79. package/build/lib/__tests__/QueryResetErrorBoundary.test.d.ts.map +0 -1
  80. package/build/lib/__tests__/queryOptions.types.test.d.ts.map +0 -1
  81. package/build/lib/__tests__/ssr-hydration.test.d.ts.map +0 -1
  82. package/build/lib/__tests__/ssr.test.d.ts.map +0 -1
  83. package/build/lib/__tests__/suspense.test.d.ts.map +0 -1
  84. package/build/lib/__tests__/useInfiniteQuery.test.d.ts.map +0 -1
  85. package/build/lib/__tests__/useIsFetching.test.d.ts.map +0 -1
  86. package/build/lib/__tests__/useIsMutating.test.d.ts.map +0 -1
  87. package/build/lib/__tests__/useMutation.test.d.ts.map +0 -1
  88. package/build/lib/__tests__/useQueries.test.d.ts.map +0 -1
  89. package/build/lib/__tests__/useQuery.test.d.ts.map +0 -1
  90. package/build/lib/__tests__/useQuery.types.test.d.ts.map +0 -1
  91. package/build/lib/__tests__/useSuspenseQueries.types.test.d.ts.map +0 -1
  92. package/build/lib/__tests__/useSuspenseQuery.types.test.d.ts.map +0 -1
  93. package/build/lib/__tests__/utils.d.ts.map +0 -1
  94. package/build/lib/errorBoundaryUtils.d.ts.map +0 -1
  95. package/build/lib/index.d.ts.map +0 -1
  96. package/build/lib/isRestoring.d.ts.map +0 -1
  97. package/build/lib/queryOptions.d.ts.map +0 -1
  98. package/build/lib/reactBatchedUpdates.d.ts.map +0 -1
  99. package/build/lib/reactBatchedUpdates.native.d.ts.map +0 -1
  100. package/build/lib/setBatchUpdatesFn.d.ts.map +0 -1
  101. package/build/lib/suspense.d.ts.map +0 -1
  102. package/build/lib/types.d.ts.map +0 -1
  103. package/build/lib/useBaseQuery.d.ts.map +0 -1
  104. package/build/lib/useInfiniteQuery.d.ts.map +0 -1
  105. package/build/lib/useIsFetching.d.ts.map +0 -1
  106. package/build/lib/useIsMutating.d.ts.map +0 -1
  107. package/build/lib/useMutation.d.ts.map +0 -1
  108. package/build/lib/useQueries.d.ts.map +0 -1
  109. package/build/lib/useQuery.d.ts.map +0 -1
  110. package/build/lib/useSuspenseQueries.d.ts.map +0 -1
  111. package/build/lib/useSuspenseQuery.d.ts.map +0 -1
  112. package/build/lib/useSyncExternalStore.d.ts.map +0 -1
  113. package/build/lib/useSyncExternalStore.native.d.ts.map +0 -1
  114. package/build/lib/utils.d.ts.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query",
3
- "version": "4.40.2",
3
+ "version": "4.42.0",
4
4
  "description": "Hooks for managing, caching and syncing asynchronous and remote data in React",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -39,23 +39,25 @@
39
39
  ],
40
40
  "devDependencies": {
41
41
  "@types/jscodeshift": "^0.11.3",
42
- "@types/react": "^18.0.14",
43
- "@types/react-dom": "^18.0.5",
42
+ "@types/react": "^19.1.9",
43
+ "@types/react-dom": "^19.1.7",
44
44
  "@types/use-sync-external-store": "^0.0.3",
45
- "react": "^18.2.0",
45
+ "react": "^19.1.1",
46
46
  "react-17": "npm:react@^17.0.2",
47
- "react-dom": "^18.2.0",
47
+ "react-18": "npm:react@^18.2.0",
48
+ "react-dom": "^19.1.1",
48
49
  "react-dom-17": "npm:react-dom@^17.0.2",
50
+ "react-dom-18": "npm:react-dom@^18.2.0",
49
51
  "jscodeshift": "^0.13.1",
50
52
  "react-error-boundary": "^3.1.4"
51
53
  },
52
54
  "dependencies": {
53
55
  "use-sync-external-store": "^1.2.0",
54
- "@tanstack/query-core": "4.40.0"
56
+ "@tanstack/query-core": "4.41.0"
55
57
  },
56
58
  "peerDependencies": {
57
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
58
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
59
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
60
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
59
61
  "react-native": "*"
60
62
  },
61
63
  "peerDependenciesMeta": {
@@ -73,7 +73,7 @@ export const QueryClientProvider = ({
73
73
  children,
74
74
  context,
75
75
  contextSharing = false,
76
- }: QueryClientProviderProps): JSX.Element => {
76
+ }: QueryClientProviderProps): React.JSX.Element => {
77
77
  React.useEffect(() => {
78
78
  client.mount()
79
79
  return () => {
@@ -0,0 +1,13 @@
1
+ import { infiniteQueryOptions } from '../infiniteQueryOptions'
2
+
3
+ describe('infiniteQueryOptions', () => {
4
+ it('should return the object received as a parameter without any modification.', () => {
5
+ const object = {
6
+ queryKey: ['key'],
7
+ queryFn: () => Promise.resolve(5),
8
+ getNextPageParam: () => null,
9
+ } as const
10
+
11
+ expect(infiniteQueryOptions(object)).toStrictEqual(object)
12
+ })
13
+ })
@@ -0,0 +1,111 @@
1
+ import { expectTypeOf } from 'expect-type'
2
+ import {
3
+ type InfiniteData,
4
+ type UseInfiniteQueryResult,
5
+ useInfiniteQuery,
6
+ useQueryClient,
7
+ } from '@tanstack/react-query'
8
+
9
+ import { useSuspenseInfiniteQuery } from '../useSuspenseInfiniteQuery'
10
+ import { infiniteQueryOptions } from '../infiniteQueryOptions'
11
+ import { doNotExecute } from './utils'
12
+ import type {
13
+ DefinedUseInfiniteQueryResult,
14
+ UseSuspenseInfiniteQueryResult,
15
+ } from '../types'
16
+
17
+ const infiniteQuery = {
18
+ options: () =>
19
+ infiniteQueryOptions({
20
+ queryKey: ['key', 1] as const,
21
+ queryFn: () => Promise.resolve({ field: 'success' }),
22
+ }),
23
+ optionsWithInitialData: () =>
24
+ infiniteQueryOptions({
25
+ queryKey: ['key', 2] as const,
26
+ queryFn: () => Promise.resolve({ field: 'success' }),
27
+ initialData: () => ({ pageParams: [], pages: [{ field: 'success' }] }),
28
+ }),
29
+ }
30
+
31
+ describe('infiniteQueryOptions', () => {
32
+ it('should be used with useInfiniteQuery', () => {
33
+ doNotExecute(() => {
34
+ expectTypeOf(useInfiniteQuery(infiniteQuery.options())).toEqualTypeOf<
35
+ UseInfiniteQueryResult<{ field: string }>
36
+ >()
37
+
38
+ expectTypeOf(
39
+ useInfiniteQuery({
40
+ ...infiniteQuery.options(),
41
+ select: (data) => ({
42
+ pages: data.pages.map(({ field }) => field),
43
+ pageParams: data.pageParams,
44
+ }),
45
+ }),
46
+ ).toEqualTypeOf<UseInfiniteQueryResult<string>>()
47
+
48
+ expectTypeOf(
49
+ useInfiniteQuery(infiniteQuery.optionsWithInitialData()),
50
+ ).toEqualTypeOf<DefinedUseInfiniteQueryResult<{ field: string }>>()
51
+
52
+ expectTypeOf(
53
+ useInfiniteQuery({
54
+ ...infiniteQuery.optionsWithInitialData(),
55
+ select: (data) => ({
56
+ pages: data.pages.map(({ field }) => field),
57
+ pageParams: data.pageParams,
58
+ }),
59
+ }),
60
+ ).toEqualTypeOf<DefinedUseInfiniteQueryResult<string>>()
61
+
62
+ expectTypeOf(
63
+ useInfiniteQuery({
64
+ queryKey: ['key', 2] as const,
65
+ queryFn: () => Promise.resolve({ field: 'success' }),
66
+ initialData: () => ({
67
+ pages: [{ field: 'success' }],
68
+ pageParams: [],
69
+ }),
70
+ select: (data) => ({
71
+ pages: data.pages.map(({ field }) => field),
72
+ pageParams: data.pageParams,
73
+ }),
74
+ }),
75
+ ).toEqualTypeOf<DefinedUseInfiniteQueryResult<string>>()
76
+ })
77
+ })
78
+ it('should be used with useSuspenseInfiniteQuery', () => {
79
+ doNotExecute(() => {
80
+ expectTypeOf(
81
+ useSuspenseInfiniteQuery(infiniteQuery.options()),
82
+ ).toEqualTypeOf<UseSuspenseInfiniteQueryResult<{ field: string }>>()
83
+
84
+ expectTypeOf(
85
+ useSuspenseInfiniteQuery({
86
+ ...infiniteQuery.options(),
87
+ select: (data) => ({
88
+ pages: data.pages.map(({ field }) => field),
89
+ pageParams: data.pageParams,
90
+ }),
91
+ }),
92
+ ).toEqualTypeOf<UseSuspenseInfiniteQueryResult<string>>()
93
+ })
94
+ })
95
+ it('should be used with useQueryClient', () => {
96
+ doNotExecute(async () => {
97
+ const queryClient = useQueryClient()
98
+
99
+ queryClient.invalidateQueries(infiniteQuery.options())
100
+ queryClient.resetQueries(infiniteQuery.options())
101
+ queryClient.removeQueries(infiniteQuery.options())
102
+ queryClient.cancelQueries(infiniteQuery.options())
103
+ queryClient.prefetchQuery(infiniteQuery.options())
104
+ queryClient.refetchQueries(infiniteQuery.options())
105
+
106
+ expectTypeOf(
107
+ await queryClient.fetchQuery(infiniteQuery.options()),
108
+ ).toEqualTypeOf<InfiniteData<{ field: string }>>()
109
+ })
110
+ })
111
+ })
@@ -19,13 +19,14 @@ const queryFn = () => Promise.resolve({ field: 'success' })
19
19
  describe('queryOptions', () => {
20
20
  it('should be used with useQuery', () => {
21
21
  doNotExecute(() => {
22
- const dd = useQuery(
23
- queryOptions({
24
- queryKey,
25
- queryFn,
26
- }),
27
- )
28
- expectTypeOf(dd).toEqualTypeOf<UseQueryResult<{ field: string }>>()
22
+ expectTypeOf(
23
+ useQuery(
24
+ queryOptions({
25
+ queryKey,
26
+ queryFn,
27
+ }),
28
+ ),
29
+ ).toEqualTypeOf<UseQueryResult<{ field: string }>>()
29
30
  expectTypeOf(
30
31
  useQuery({
31
32
  ...queryOptions({
@@ -1,9 +1,8 @@
1
1
  import * as React from 'react'
2
2
  import ReactDOM from 'react-dom'
3
- import ReactDOMTestUtils from 'react-dom/test-utils'
3
+ import { act } from '@testing-library/react'
4
4
  import ReactDOMServer from 'react-dom/server'
5
- // eslint-disable-next-line import/no-unresolved -- types only for module augmentation
6
- import type {} from 'react-dom/next'
5
+ import ReactDOMClient from 'react-dom/client'
7
6
 
8
7
  import {
9
8
  QueryCache,
@@ -14,12 +13,13 @@ import {
14
13
  } from '..'
15
14
  import { createQueryClient, setIsServer, sleep } from './utils'
16
15
 
17
- const isReact18 = () => (process.env.REACTJS_VERSION || '18') === '18'
16
+ const isReact18 = () => (process.env.REACTJS_VERSION || '19') === '18'
17
+ const isReact17 = () => (process.env.REACTJS_VERSION || '19') === '17'
18
18
 
19
19
  const ReactHydrate = (element: React.ReactElement, container: Element) => {
20
20
  if (isReact18()) {
21
21
  let root: any
22
- ReactDOMTestUtils.act(() => {
22
+ act(() => {
23
23
  // @ts-expect-error
24
24
  root = ReactDOM.hydrateRoot(container, element)
25
25
  })
@@ -28,9 +28,21 @@ const ReactHydrate = (element: React.ReactElement, container: Element) => {
28
28
  }
29
29
  }
30
30
 
31
- ReactDOM.hydrate(element, container)
31
+ if (isReact17()) {
32
+ // @ts-expect-error
33
+ ReactDOM.hydrate(element, container)
34
+ return () => {
35
+ // @ts-expect-error
36
+ ReactDOM.unmountComponentAtNode(container)
37
+ }
38
+ }
39
+
40
+ let root: any
41
+ React.act(() => {
42
+ root = ReactDOMClient.hydrateRoot(container, element)
43
+ })
32
44
  return () => {
33
- ReactDOM.unmountComponentAtNode(container)
45
+ root.unmount()
34
46
  }
35
47
  }
36
48
 
@@ -54,6 +66,7 @@ describe('Server side rendering with de/rehydration', () => {
54
66
  // @ts-expect-error we expect IS_REACT_ACT_ENVIRONMENT to exist
55
67
  globalThis.IS_REACT_ACT_ENVIRONMENT = previousIsReactActEnvironment
56
68
  })
69
+
57
70
  it('should not mismatch on success', async () => {
58
71
  const consoleMock = jest.spyOn(console, 'error')
59
72
  consoleMock.mockImplementation(() => undefined)
@@ -9,7 +9,13 @@ import {
9
9
  useQuery,
10
10
  useQueryErrorResetBoundary,
11
11
  } from '..'
12
- import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
12
+ import {
13
+ createQueryClient,
14
+ queryKey,
15
+ reactVersion,
16
+ renderWithClient,
17
+ sleep,
18
+ } from './utils'
13
19
  import type { UseInfiniteQueryResult, UseQueryResult } from '..'
14
20
 
15
21
  describe("useQuery's in Suspense mode", () => {
@@ -60,7 +66,7 @@ describe("useQuery's in Suspense mode", () => {
60
66
 
61
67
  await waitFor(() => rendered.getByText('data: 2'))
62
68
 
63
- expect(renders).toBe(4)
69
+ expect(renders).toBe(reactVersion() === '19' ? 6 : 4)
64
70
  expect(states.length).toBe(2)
65
71
  expect(states[0]).toMatchObject({ data: 1, status: 'success' })
66
72
  expect(states[1]).toMatchObject({ data: 2, status: 'success' })
@@ -221,7 +227,9 @@ describe("useQuery's in Suspense mode", () => {
221
227
 
222
228
  await waitFor(() => rendered.getByText('rendered'))
223
229
 
224
- await waitFor(() => expect(successFn).toHaveBeenCalledTimes(1))
230
+ await waitFor(() =>
231
+ expect(successFn).toHaveBeenCalledTimes(reactVersion() === '19' ? 2 : 1),
232
+ )
225
233
  await waitFor(() => expect(successFn).toHaveBeenCalledWith('selected'))
226
234
  })
227
235
 
@@ -273,7 +281,9 @@ describe("useQuery's in Suspense mode", () => {
273
281
 
274
282
  await waitFor(() => rendered.getByText('second'))
275
283
 
276
- await waitFor(() => expect(successFn1).toHaveBeenCalledTimes(1))
284
+ await waitFor(() =>
285
+ expect(successFn1).toHaveBeenCalledTimes(reactVersion() === '19' ? 2 : 1),
286
+ )
277
287
  await waitFor(() => expect(successFn2).toHaveBeenCalledTimes(1))
278
288
  })
279
289
 
@@ -1007,8 +1017,10 @@ describe("useQuery's in Suspense mode", () => {
1007
1017
  }),
1008
1018
  )
1009
1019
 
1010
- expect(renders).toBe(2)
1011
- expect(rendered.queryByText('rendered')).not.toBeNull()
1020
+ expect(renders).toBe(reactVersion() === '19' ? 3 : 2)
1021
+ await waitFor(() => {
1022
+ expect(rendered.queryByText('rendered')).not.toBeNull()
1023
+ })
1012
1024
  })
1013
1025
  })
1014
1026
 
@@ -735,7 +735,7 @@ describe('useMutation', () => {
735
735
  })
736
736
 
737
737
  it('should be able to throw an error when useErrorBoundary is a function that returns true', async () => {
738
- let boundary = false
738
+ let callBoundaryCount = 0
739
739
  function Page() {
740
740
  const { mutate, error } = useMutation<string, Error>(
741
741
  () => {
@@ -745,8 +745,8 @@ describe('useMutation', () => {
745
745
  },
746
746
  {
747
747
  useErrorBoundary: () => {
748
- boundary = !boundary
749
- return !boundary
748
+ callBoundaryCount++
749
+ return callBoundaryCount > 1
750
750
  },
751
751
  },
752
752
  )
@@ -10,6 +10,7 @@ import {
10
10
  expectType,
11
11
  expectTypeNotAny,
12
12
  queryKey,
13
+ reactVersion,
13
14
  renderWithClient,
14
15
  sleep,
15
16
  } from './utils'
@@ -281,41 +282,169 @@ describe('useQueries', () => {
281
282
  await waitFor(() => rendered.getByText('data1: 5, data2: 10'))
282
283
  await waitFor(() => rendered.getByText('isFetching: false'))
283
284
 
284
- await waitFor(() => expect(states.length).toBe(6))
285
-
286
- expect(states[0]).toMatchObject([
287
- {
288
- status: 'loading',
289
- data: undefined,
290
- isPreviousData: false,
291
- isFetching: true,
292
- },
293
- {
294
- status: 'loading',
295
- data: undefined,
296
- isPreviousData: false,
297
- isFetching: true,
298
- },
299
- ])
300
- expect(states[1]).toMatchObject([
301
- { status: 'success', data: 5, isPreviousData: false, isFetching: false },
302
- { status: 'success', data: 10, isPreviousData: false, isFetching: false },
303
- ])
304
- expect(states[2]).toMatchObject([
305
- { status: 'success', data: 10, isPreviousData: false, isFetching: false },
306
- ])
307
- expect(states[3]).toMatchObject([
308
- { status: 'success', data: 5, isPreviousData: false, isFetching: true },
309
- { status: 'success', data: 10, isPreviousData: false, isFetching: false },
310
- ])
311
- expect(states[4]).toMatchObject([
312
- { status: 'success', data: 5, isPreviousData: false, isFetching: true },
313
- { status: 'success', data: 10, isPreviousData: false, isFetching: false },
314
- ])
315
- expect(states[5]).toMatchObject([
316
- { status: 'success', data: 5, isPreviousData: false, isFetching: false },
317
- { status: 'success', data: 10, isPreviousData: false, isFetching: false },
318
- ])
285
+ await waitFor(() =>
286
+ expect(states.length).toBe(reactVersion() === '18' ? 6 : 7),
287
+ )
288
+
289
+ if (reactVersion() === '18') {
290
+ expect(states[0]).toMatchObject([
291
+ {
292
+ status: 'loading',
293
+ data: undefined,
294
+ isPreviousData: false,
295
+ isFetching: true,
296
+ },
297
+ {
298
+ status: 'loading',
299
+ data: undefined,
300
+ isPreviousData: false,
301
+ isFetching: true,
302
+ },
303
+ ])
304
+ expect(states[1]).toMatchObject([
305
+ {
306
+ status: 'success',
307
+ data: 5,
308
+ isPreviousData: false,
309
+ isFetching: false,
310
+ },
311
+ {
312
+ status: 'success',
313
+ data: 10,
314
+ isPreviousData: false,
315
+ isFetching: false,
316
+ },
317
+ ])
318
+ expect(states[2]).toMatchObject([
319
+ {
320
+ status: 'success',
321
+ data: 10,
322
+ isPreviousData: false,
323
+ isFetching: false,
324
+ },
325
+ ])
326
+ expect(states[3]).toMatchObject([
327
+ { status: 'success', data: 5, isPreviousData: false, isFetching: true },
328
+ {
329
+ status: 'success',
330
+ data: 10,
331
+ isPreviousData: false,
332
+ isFetching: false,
333
+ },
334
+ ])
335
+ expect(states[4]).toMatchObject([
336
+ { status: 'success', data: 5, isPreviousData: false, isFetching: true },
337
+ {
338
+ status: 'success',
339
+ data: 10,
340
+ isPreviousData: false,
341
+ isFetching: false,
342
+ },
343
+ ])
344
+ expect(states[5]).toMatchObject([
345
+ {
346
+ status: 'success',
347
+ data: 5,
348
+ isPreviousData: false,
349
+ isFetching: false,
350
+ },
351
+ {
352
+ status: 'success',
353
+ data: 10,
354
+ isPreviousData: false,
355
+ isFetching: false,
356
+ },
357
+ ])
358
+ }
359
+
360
+ if (reactVersion() === '19') {
361
+ expect(states[0]).toMatchObject([
362
+ {
363
+ status: 'loading',
364
+ data: undefined,
365
+ isPreviousData: false,
366
+ isFetching: true,
367
+ },
368
+ {
369
+ status: 'loading',
370
+ data: undefined,
371
+ isPreviousData: false,
372
+ isFetching: true,
373
+ },
374
+ ])
375
+ expect(states[1]).toMatchObject([
376
+ {
377
+ status: 'success',
378
+ data: 5,
379
+ isPreviousData: false,
380
+ isFetching: false,
381
+ },
382
+ {
383
+ status: 'success',
384
+ data: 10,
385
+ isPreviousData: false,
386
+ isFetching: false,
387
+ },
388
+ ])
389
+ expect(states[2]).toMatchObject([
390
+ {
391
+ status: 'success',
392
+ data: 10,
393
+ isPreviousData: false,
394
+ isFetching: false,
395
+ },
396
+ ])
397
+ expect(states[3]).toMatchObject([
398
+ {
399
+ status: 'success',
400
+ data: 10,
401
+ isPreviousData: false,
402
+ isFetching: false,
403
+ },
404
+ ])
405
+ expect(states[4]).toMatchObject([
406
+ {
407
+ status: 'success',
408
+ data: 5,
409
+ isPreviousData: false,
410
+ isFetching: true,
411
+ },
412
+ {
413
+ status: 'success',
414
+ data: 10,
415
+ isPreviousData: false,
416
+ isFetching: false,
417
+ },
418
+ ])
419
+ expect(states[5]).toMatchObject([
420
+ {
421
+ status: 'success',
422
+ data: 5,
423
+ isPreviousData: false,
424
+ isFetching: true,
425
+ },
426
+ {
427
+ status: 'success',
428
+ data: 10,
429
+ isPreviousData: false,
430
+ isFetching: false,
431
+ },
432
+ ])
433
+ expect(states[6]).toMatchObject([
434
+ {
435
+ status: 'success',
436
+ data: 5,
437
+ isPreviousData: false,
438
+ isFetching: false,
439
+ },
440
+ {
441
+ status: 'success',
442
+ data: 10,
443
+ isPreviousData: false,
444
+ isFetching: false,
445
+ },
446
+ ])
447
+ }
319
448
  })
320
449
 
321
450
  it('handles type parameter - tuple of tuples', async () => {
@@ -11,6 +11,7 @@ import {
11
11
  mockNavigatorOnLine,
12
12
  mockVisibilityState,
13
13
  queryKey,
14
+ reactVersion,
14
15
  renderWithClient,
15
16
  setActTimeout,
16
17
  sleep,
@@ -6204,12 +6205,12 @@ describe('useQuery', () => {
6204
6205
  spy.mockClear()
6205
6206
  fireEvent.click(rendered.getByRole('button', { name: /1/ }))
6206
6207
  await waitFor(() => rendered.getByText('Rendered Id: 1'))
6207
- expect(spy).toHaveBeenCalledTimes(1)
6208
+ expect(spy).toHaveBeenCalledTimes(reactVersion() === '19' ? 2 : 1)
6208
6209
 
6209
6210
  spy.mockClear()
6210
6211
  fireEvent.click(rendered.getByRole('button', { name: /2/ }))
6211
6212
  await waitFor(() => rendered.getByText('Rendered Id: 2'))
6212
- expect(spy).toHaveBeenCalledTimes(1)
6213
+ expect(spy).toHaveBeenCalledTimes(reactVersion() === '18' ? 1 : 2)
6213
6214
  })
6214
6215
  it('should not cause an infinite render loop when using unstable callback ref', async () => {
6215
6216
  const key = queryKey()
@@ -0,0 +1,115 @@
1
+ import { expectTypeOf } from 'expect-type'
2
+ import { infiniteQueryOptions, useSuspenseInfiniteQuery } from '..'
3
+ import { doNotExecute, sleep } from './utils'
4
+ import type { UseSuspenseInfiniteQueryResult } from '..'
5
+
6
+ import type { InfiniteData } from '@tanstack/react-query'
7
+
8
+ const queryKey = ['key'] as const
9
+ const queryFn = () => sleep(10).then(() => ({ text: 'response' }))
10
+
11
+ describe('useSuspenseInfiniteQuery', () => {
12
+ it('type check', () => {
13
+ doNotExecute(() => {
14
+ // @ts-expect-error no arg
15
+ useSuspenseInfiniteQuery()
16
+
17
+ useSuspenseInfiniteQuery({
18
+ queryKey,
19
+ queryFn,
20
+ // @ts-expect-error no suspense
21
+ suspense: boolean,
22
+ })
23
+ useSuspenseInfiniteQuery({
24
+ queryKey,
25
+ queryFn,
26
+ // @ts-expect-error no useErrorBoundary
27
+ useErrorBoundary: boolean,
28
+ })
29
+ useSuspenseInfiniteQuery({
30
+ queryKey,
31
+ queryFn,
32
+ // @ts-expect-error no enabled
33
+ enabled: boolean,
34
+ })
35
+ useSuspenseInfiniteQuery({
36
+ queryKey,
37
+ queryFn,
38
+ // @ts-expect-error no placeholderData
39
+ placeholderData: 'placeholder',
40
+ })
41
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
42
+ useSuspenseInfiniteQuery({
43
+ queryKey,
44
+ queryFn,
45
+ // @ts-expect-error no isPlaceholderData
46
+ }).isPlaceholderData
47
+ useSuspenseInfiniteQuery({
48
+ queryKey,
49
+ queryFn,
50
+ //@ts-expect-error no networkMode
51
+ networkMode: 'always',
52
+ })
53
+
54
+ const infiniteQuery = useSuspenseInfiniteQuery({ queryKey, queryFn })
55
+ expectTypeOf(infiniteQuery).toEqualTypeOf<
56
+ UseSuspenseInfiniteQueryResult<{ text: string }>
57
+ >()
58
+ expectTypeOf(infiniteQuery.data).toEqualTypeOf<
59
+ InfiniteData<{ text: string }>
60
+ >()
61
+ expectTypeOf(infiniteQuery.status).toEqualTypeOf<'error' | 'success'>()
62
+
63
+ const selectedInfiniteQuery = useSuspenseInfiniteQuery({
64
+ queryKey,
65
+ queryFn,
66
+ select: (data) => ({
67
+ pages: data.pages.map(({ text }) => text),
68
+ pageParams: data.pageParams,
69
+ }),
70
+ })
71
+ expectTypeOf(selectedInfiniteQuery).toEqualTypeOf<
72
+ UseSuspenseInfiniteQueryResult<string>
73
+ >()
74
+ expectTypeOf(selectedInfiniteQuery.data).toEqualTypeOf<
75
+ InfiniteData<string>
76
+ >()
77
+ expectTypeOf(selectedInfiniteQuery.status).toEqualTypeOf<
78
+ 'error' | 'success'
79
+ >()
80
+
81
+ const options = infiniteQueryOptions({
82
+ queryKey,
83
+ queryFn,
84
+ })
85
+
86
+ const infiniteQueryWithOptions = useSuspenseInfiniteQuery(options)
87
+ expectTypeOf(infiniteQueryWithOptions).toEqualTypeOf<
88
+ UseSuspenseInfiniteQueryResult<{ text: string }>
89
+ >()
90
+ expectTypeOf(infiniteQueryWithOptions.data).toEqualTypeOf<
91
+ InfiniteData<{ text: string }>
92
+ >()
93
+ expectTypeOf(infiniteQueryWithOptions.status).toEqualTypeOf<
94
+ 'error' | 'success'
95
+ >()
96
+
97
+ const selectedInfiniteQueryWithOptions = useSuspenseInfiniteQuery({
98
+ ...options,
99
+ select: (data) => ({
100
+ pages: data.pages.map(({ text }) => text),
101
+ pageParams: data.pageParams,
102
+ }),
103
+ })
104
+ expectTypeOf(selectedInfiniteQueryWithOptions).toEqualTypeOf<
105
+ UseSuspenseInfiniteQueryResult<string>
106
+ >()
107
+ expectTypeOf(selectedInfiniteQueryWithOptions.data).toEqualTypeOf<
108
+ InfiniteData<string>
109
+ >()
110
+ expectTypeOf(selectedInfiniteQueryWithOptions.status).toEqualTypeOf<
111
+ 'error' | 'success'
112
+ >()
113
+ })
114
+ })
115
+ })