@tanstack/react-query 4.29.23 → 4.30.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 (90) hide show
  1. package/build/lib/Hydrate.d.ts.map +1 -1
  2. package/build/lib/Hydrate.esm.js.map +1 -1
  3. package/build/lib/Hydrate.js.map +1 -1
  4. package/build/lib/Hydrate.mjs.map +1 -1
  5. package/build/lib/__tests__/utils.d.ts +1 -1
  6. package/build/lib/__tests__/utils.d.ts.map +1 -1
  7. package/build/lib/errorBoundaryUtils.d.ts.map +1 -1
  8. package/build/lib/errorBoundaryUtils.esm.js.map +1 -1
  9. package/build/lib/errorBoundaryUtils.js.map +1 -1
  10. package/build/lib/errorBoundaryUtils.mjs.map +1 -1
  11. package/build/lib/reactBatchedUpdates.d.ts.map +1 -1
  12. package/build/lib/reactBatchedUpdates.esm.js.map +1 -1
  13. package/build/lib/reactBatchedUpdates.js.map +1 -1
  14. package/build/lib/reactBatchedUpdates.mjs.map +1 -1
  15. package/build/lib/reactBatchedUpdates.native.d.ts.map +1 -1
  16. package/build/lib/types.d.ts +1 -1
  17. package/build/lib/types.d.ts.map +1 -1
  18. package/build/lib/useBaseQuery.d.ts.map +1 -1
  19. package/build/lib/useBaseQuery.esm.js +1 -1
  20. package/build/lib/useBaseQuery.esm.js.map +1 -1
  21. package/build/lib/useBaseQuery.js +1 -1
  22. package/build/lib/useBaseQuery.js.map +1 -1
  23. package/build/lib/useBaseQuery.mjs +1 -1
  24. package/build/lib/useBaseQuery.mjs.map +1 -1
  25. package/build/lib/useInfiniteQuery.d.ts.map +1 -1
  26. package/build/lib/useInfiniteQuery.esm.js.map +1 -1
  27. package/build/lib/useInfiniteQuery.js.map +1 -1
  28. package/build/lib/useInfiniteQuery.mjs.map +1 -1
  29. package/build/lib/useIsFetching.d.ts +1 -1
  30. package/build/lib/useIsFetching.d.ts.map +1 -1
  31. package/build/lib/useIsFetching.esm.js.map +1 -1
  32. package/build/lib/useIsFetching.js.map +1 -1
  33. package/build/lib/useIsFetching.mjs.map +1 -1
  34. package/build/lib/useIsMutating.d.ts +1 -1
  35. package/build/lib/useIsMutating.d.ts.map +1 -1
  36. package/build/lib/useIsMutating.esm.js +1 -1
  37. package/build/lib/useIsMutating.esm.js.map +1 -1
  38. package/build/lib/useIsMutating.js +1 -1
  39. package/build/lib/useIsMutating.js.map +1 -1
  40. package/build/lib/useIsMutating.mjs +1 -1
  41. package/build/lib/useIsMutating.mjs.map +1 -1
  42. package/build/lib/useMutation.d.ts.map +1 -1
  43. package/build/lib/useMutation.esm.js +1 -1
  44. package/build/lib/useMutation.esm.js.map +1 -1
  45. package/build/lib/useMutation.js +1 -1
  46. package/build/lib/useMutation.js.map +1 -1
  47. package/build/lib/useMutation.mjs +1 -1
  48. package/build/lib/useMutation.mjs.map +1 -1
  49. package/build/lib/useQueries.d.ts +1 -1
  50. package/build/lib/useQueries.d.ts.map +1 -1
  51. package/build/lib/useQueries.esm.js +1 -3
  52. package/build/lib/useQueries.esm.js.map +1 -1
  53. package/build/lib/useQueries.js +1 -3
  54. package/build/lib/useQueries.js.map +1 -1
  55. package/build/lib/useQueries.mjs +1 -3
  56. package/build/lib/useQueries.mjs.map +1 -1
  57. package/build/lib/useQuery.d.ts.map +1 -1
  58. package/build/lib/useQuery.esm.js.map +1 -1
  59. package/build/lib/useQuery.js.map +1 -1
  60. package/build/lib/useQuery.mjs.map +1 -1
  61. package/build/umd/index.development.js +3 -4
  62. package/build/umd/index.development.js.map +1 -1
  63. package/build/umd/index.production.js +1 -1
  64. package/build/umd/index.production.js.map +1 -1
  65. package/package.json +2 -2
  66. package/src/Hydrate.tsx +1 -1
  67. package/src/__tests__/Hydrate.test.tsx +4 -4
  68. package/src/__tests__/QueryClientProvider.test.tsx +2 -2
  69. package/src/__tests__/QueryResetErrorBoundary.test.tsx +1 -1
  70. package/src/__tests__/ssr-hydration.test.tsx +2 -2
  71. package/src/__tests__/ssr.test.tsx +2 -2
  72. package/src/__tests__/suspense.test.tsx +1 -1
  73. package/src/__tests__/useInfiniteQuery.test.tsx +1 -1
  74. package/src/__tests__/useIsFetching.test.tsx +1 -1
  75. package/src/__tests__/useIsMutating.test.tsx +3 -3
  76. package/src/__tests__/useMutation.test.tsx +2 -2
  77. package/src/__tests__/useQueries.test.tsx +1 -1
  78. package/src/__tests__/useQuery.test.tsx +252 -85
  79. package/src/__tests__/utils.tsx +2 -2
  80. package/src/errorBoundaryUtils.ts +2 -2
  81. package/src/reactBatchedUpdates.native.ts +1 -0
  82. package/src/reactBatchedUpdates.ts +1 -0
  83. package/src/types.ts +4 -4
  84. package/src/useBaseQuery.ts +4 -4
  85. package/src/useInfiniteQuery.ts +3 -3
  86. package/src/useIsFetching.ts +2 -2
  87. package/src/useIsMutating.ts +3 -3
  88. package/src/useMutation.ts +5 -5
  89. package/src/useQueries.ts +5 -5
  90. package/src/useQuery.ts +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query",
3
- "version": "4.29.23",
3
+ "version": "4.30.0",
4
4
  "description": "Hooks for managing, caching and syncing asynchronous and remote data in React",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
@@ -47,7 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "use-sync-external-store": "^1.2.0",
50
- "@tanstack/query-core": "4.29.23"
50
+ "@tanstack/query-core": "4.30.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
package/src/Hydrate.tsx CHANGED
@@ -1,9 +1,9 @@
1
1
  'use client'
2
2
  import * as React from 'react'
3
3
 
4
- import type { HydrateOptions } from '@tanstack/query-core'
5
4
  import { hydrate } from '@tanstack/query-core'
6
5
  import { useQueryClient } from './QueryClientProvider'
6
+ import type { HydrateOptions } from '@tanstack/query-core'
7
7
  import type { ContextOptions } from './types'
8
8
 
9
9
  export function useHydrate(
@@ -1,17 +1,17 @@
1
1
  import * as React from 'react'
2
2
  import { render } from '@testing-library/react'
3
3
 
4
+ import * as coreModule from '@tanstack/query-core'
4
5
  import {
6
+ Hydrate,
7
+ QueryCache,
5
8
  QueryClient,
6
9
  QueryClientProvider,
7
- QueryCache,
8
- useQuery,
9
10
  dehydrate,
10
11
  useHydrate,
11
- Hydrate,
12
+ useQuery,
12
13
  } from '@tanstack/react-query'
13
14
  import { createQueryClient, sleep } from './utils'
14
- import * as coreModule from '@tanstack/query-core'
15
15
 
16
16
  describe('React hydration', () => {
17
17
  const fetchData: (value: string) => Promise<string> = (value) =>
@@ -2,14 +2,14 @@ import * as React from 'react'
2
2
  import { render, waitFor } from '@testing-library/react'
3
3
  import { renderToString } from 'react-dom/server'
4
4
 
5
- import { sleep, queryKey, createQueryClient } from './utils'
6
5
  import {
6
+ QueryCache,
7
7
  QueryClient,
8
8
  QueryClientProvider,
9
- QueryCache,
10
9
  useQuery,
11
10
  useQueryClient,
12
11
  } from '..'
12
+ import { createQueryClient, queryKey, sleep } from './utils'
13
13
 
14
14
  describe('QueryClientProvider', () => {
15
15
  test('sets a specific cache for all queries to use', async () => {
@@ -2,8 +2,8 @@ import { fireEvent, waitFor } from '@testing-library/react'
2
2
  import { ErrorBoundary } from 'react-error-boundary'
3
3
  import * as React from 'react'
4
4
 
5
- import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
6
5
  import { QueryCache, QueryErrorResetBoundary, useQueries, useQuery } from '..'
6
+ import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
7
7
 
8
8
  // TODO: This should be removed with the types for react-error-boundary get updated.
9
9
  declare module 'react-error-boundary' {
@@ -6,11 +6,11 @@ import ReactDOMServer from 'react-dom/server'
6
6
  import type {} from 'react-dom/next'
7
7
 
8
8
  import {
9
- useQuery,
10
- QueryClientProvider,
11
9
  QueryCache,
10
+ QueryClientProvider,
12
11
  dehydrate,
13
12
  hydrate,
13
+ useQuery,
14
14
  } from '..'
15
15
  import { createQueryClient, setIsServer, sleep } from './utils'
16
16
 
@@ -6,8 +6,8 @@ import * as React from 'react'
6
6
  // @ts-ignore
7
7
  import { renderToString } from 'react-dom/server'
8
8
 
9
- import { sleep, queryKey, createQueryClient } from './utils'
10
- import { useQuery, QueryClientProvider, QueryCache, useInfiniteQuery } from '..'
9
+ import { QueryCache, QueryClientProvider, useInfiniteQuery, useQuery } from '..'
10
+ import { createQueryClient, queryKey, sleep } from './utils'
11
11
 
12
12
  describe('Server Side Rendering', () => {
13
13
  it('should not trigger fetch', () => {
@@ -1,7 +1,6 @@
1
1
  import { fireEvent, waitFor } from '@testing-library/react'
2
2
  import * as React from 'react'
3
3
  import { ErrorBoundary } from 'react-error-boundary'
4
- import type { UseInfiniteQueryResult, UseQueryResult } from '..'
5
4
  import {
6
5
  QueryCache,
7
6
  QueryErrorResetBoundary,
@@ -11,6 +10,7 @@ import {
11
10
  useQueryErrorResetBoundary,
12
11
  } from '..'
13
12
  import { createQueryClient, queryKey, renderWithClient, sleep } from './utils'
13
+ import type { UseInfiniteQueryResult, UseQueryResult } from '..'
14
14
 
15
15
  describe("useQuery's in Suspense mode", () => {
16
16
  const queryCache = new QueryCache()
@@ -1,6 +1,7 @@
1
1
  import { fireEvent, waitFor } from '@testing-library/react'
2
2
  import * as React from 'react'
3
3
 
4
+ import { QueryCache, useInfiniteQuery } from '..'
4
5
  import {
5
6
  createQueryClient,
6
7
  queryKey,
@@ -13,7 +14,6 @@ import type {
13
14
  QueryFunctionContext,
14
15
  UseInfiniteQueryResult,
15
16
  } from '..'
16
- import { QueryCache, useInfiniteQuery } from '..'
17
17
 
18
18
  interface Result {
19
19
  items: number[]
@@ -2,6 +2,7 @@ import { fireEvent, waitFor } from '@testing-library/react'
2
2
  import * as React from 'react'
3
3
  import { ErrorBoundary } from 'react-error-boundary'
4
4
 
5
+ import { QueryCache, useIsFetching, useQuery } from '..'
5
6
  import {
6
7
  createQueryClient,
7
8
  queryKey,
@@ -10,7 +11,6 @@ import {
10
11
  sleep,
11
12
  } from './utils'
12
13
  import type { QueryClient } from '..'
13
- import { QueryCache, useIsFetching, useQuery } from '..'
14
14
 
15
15
  describe('useIsFetching', () => {
16
16
  // See https://github.com/tannerlinsley/react-query/issues/105
@@ -1,16 +1,16 @@
1
1
  import { fireEvent, waitFor } from '@testing-library/react'
2
2
  import * as React from 'react'
3
+ import { ErrorBoundary } from 'react-error-boundary'
4
+ import { QueryClient } from '@tanstack/query-core'
3
5
  import { useIsMutating } from '../useIsMutating'
4
6
  import { useMutation } from '../useMutation'
7
+ import * as MutationCacheModule from '../../../query-core/src/mutationCache'
5
8
  import {
6
9
  createQueryClient,
7
10
  renderWithClient,
8
11
  setActTimeout,
9
12
  sleep,
10
13
  } from './utils'
11
- import { ErrorBoundary } from 'react-error-boundary'
12
- import { QueryClient } from '@tanstack/query-core'
13
- import * as MutationCacheModule from '../../../query-core/src/mutationCache'
14
14
 
15
15
  describe('useIsMutating', () => {
16
16
  it('should return the number of fetching mutations', async () => {
@@ -3,9 +3,7 @@ import '@testing-library/jest-dom'
3
3
  import * as React from 'react'
4
4
  import { ErrorBoundary } from 'react-error-boundary'
5
5
 
6
- import type { QueryClient } from '..'
7
6
  import { MutationCache, QueryCache, useMutation } from '..'
8
- import type { UseMutationResult } from '../types'
9
7
  import {
10
8
  createQueryClient,
11
9
  mockNavigatorOnLine,
@@ -14,6 +12,8 @@ import {
14
12
  setActTimeout,
15
13
  sleep,
16
14
  } from './utils'
15
+ import type { QueryClient } from '..'
16
+ import type { UseMutationResult } from '../types'
17
17
 
18
18
  describe('useMutation', () => {
19
19
  const queryCache = new QueryCache()
@@ -4,6 +4,7 @@ import { ErrorBoundary } from 'react-error-boundary'
4
4
 
5
5
  import * as QueriesObserverModule from '../../../query-core/src/queriesObserver'
6
6
 
7
+ import { QueriesObserver, QueryCache, useQueries } from '..'
7
8
  import {
8
9
  createQueryClient,
9
10
  expectType,
@@ -20,7 +21,6 @@ import type {
20
21
  UseQueryOptions,
21
22
  UseQueryResult,
22
23
  } from '..'
23
- import { QueriesObserver, QueryCache, useQueries } from '..'
24
24
  import type { QueryFunctionContext } from '@tanstack/query-core'
25
25
 
26
26
  describe('useQueries', () => {
@@ -1,6 +1,8 @@
1
1
  import { act, fireEvent, 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 { QueryCache, useQuery } from '..'
4
6
  import {
5
7
  Blink,
6
8
  createQueryClient,
@@ -20,8 +22,6 @@ import type {
20
22
  UseQueryOptions,
21
23
  UseQueryResult,
22
24
  } from '..'
23
- import { QueryCache, useQuery } from '..'
24
- import { ErrorBoundary } from 'react-error-boundary'
25
25
 
26
26
  describe('useQuery', () => {
27
27
  const queryCache = new QueryCache()
@@ -1018,46 +1018,6 @@ describe('useQuery', () => {
1018
1018
  expect(states[1]).toMatchObject({ data: 'test' })
1019
1019
  })
1020
1020
 
1021
- it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {
1022
- const key = queryKey()
1023
- const states: UseQueryResult<string>[] = []
1024
-
1025
- function Page() {
1026
- const state = useQuery(key, () => ({ name: 'test' }), {
1027
- select: (data) => data.name,
1028
- notifyOnChangeProps: ['data'],
1029
- })
1030
-
1031
- states.push(state)
1032
-
1033
- return (
1034
- <div>
1035
- <div>{state.data}</div>
1036
- <button onClick={() => state.refetch()}>refetch</button>
1037
- </div>
1038
- )
1039
- }
1040
-
1041
- const rendered = renderWithClient(queryClient, <Page />)
1042
-
1043
- await waitFor(() => {
1044
- rendered.getByText('test')
1045
- })
1046
-
1047
- fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
1048
-
1049
- await waitFor(() => {
1050
- rendered.getByText('test')
1051
- })
1052
-
1053
- expect(states[0]).toMatchObject({ data: undefined })
1054
- expect(states[1]).toMatchObject({ data: 'test' })
1055
-
1056
- // make sure no additional renders happen
1057
- await sleep(50)
1058
- expect(states.length).toBe(2)
1059
- })
1060
-
1061
1021
  it('should throw an error when a selector throws', async () => {
1062
1022
  const key = queryKey()
1063
1023
  const states: UseQueryResult<string>[] = []
@@ -2223,60 +2183,267 @@ describe('useQuery', () => {
2223
2183
  expect(states[2]).toMatchObject({ isStale: true })
2224
2184
  })
2225
2185
 
2226
- it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
2227
- const key = queryKey()
2228
- const states: UseQueryResult<string>[] = []
2186
+ describe('notifyOnChangeProps', () => {
2187
+ it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
2188
+ const key = queryKey()
2189
+ const states: UseQueryResult<string>[] = []
2229
2190
 
2230
- function Page() {
2231
- const state = useQuery(
2232
- key,
2233
- async () => {
2234
- await sleep(5)
2235
- return 'test'
2236
- },
2237
- {
2238
- notifyOnChangeProps: ['data'],
2239
- },
2240
- )
2191
+ function Page() {
2192
+ const state = useQuery(
2193
+ key,
2194
+ async () => {
2195
+ await sleep(5)
2196
+ return 'test'
2197
+ },
2198
+ {
2199
+ notifyOnChangeProps: ['data'],
2200
+ },
2201
+ )
2241
2202
 
2242
- states.push(state)
2203
+ states.push(state)
2243
2204
 
2244
- return (
2245
- <>
2246
- <button
2247
- onClick={async () => {
2248
- await state.refetch()
2249
- }}
2250
- >
2251
- refetch
2252
- </button>
2205
+ return (
2206
+ <>
2207
+ <button
2208
+ onClick={async () => {
2209
+ await state.refetch()
2210
+ }}
2211
+ >
2212
+ refetch
2213
+ </button>
2253
2214
 
2254
- <div>{state.data}</div>
2255
- </>
2256
- )
2257
- }
2215
+ <div>{state.data}</div>
2216
+ </>
2217
+ )
2218
+ }
2258
2219
 
2259
- const rendered = renderWithClient(queryClient, <Page />)
2220
+ const rendered = renderWithClient(queryClient, <Page />)
2260
2221
 
2261
- await waitFor(() => {
2262
- rendered.getByText('test')
2222
+ await waitFor(() => {
2223
+ rendered.getByText('test')
2224
+ })
2225
+
2226
+ fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
2227
+
2228
+ // sleep is required to make sure no additional renders happen after click
2229
+ await sleep(20)
2230
+
2231
+ expect(states.length).toBe(2)
2232
+ expect(states[0]).toMatchObject({
2233
+ data: undefined,
2234
+ status: 'loading',
2235
+ isFetching: true,
2236
+ })
2237
+ expect(states[1]).toMatchObject({
2238
+ data: 'test',
2239
+ status: 'success',
2240
+ isFetching: false,
2241
+ })
2263
2242
  })
2264
2243
 
2265
- fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
2244
+ it('should not re-render when it should only re-render only data change and the selected data did not change', async () => {
2245
+ const key = queryKey()
2246
+ const states: UseQueryResult<string>[] = []
2266
2247
 
2267
- // sleep is required to make sure no additional renders happen after click
2268
- await sleep(20)
2248
+ function Page() {
2249
+ const state = useQuery(key, () => ({ name: 'test' }), {
2250
+ select: (data) => data.name,
2251
+ notifyOnChangeProps: ['data'],
2252
+ })
2269
2253
 
2270
- expect(states.length).toBe(2)
2271
- expect(states[0]).toMatchObject({
2272
- data: undefined,
2273
- status: 'loading',
2274
- isFetching: true,
2254
+ states.push(state)
2255
+
2256
+ return (
2257
+ <div>
2258
+ <div>{state.data}</div>
2259
+ <button onClick={() => state.refetch()}>refetch</button>
2260
+ </div>
2261
+ )
2262
+ }
2263
+
2264
+ const rendered = renderWithClient(queryClient, <Page />)
2265
+
2266
+ await waitFor(() => {
2267
+ rendered.getByText('test')
2268
+ })
2269
+
2270
+ fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
2271
+
2272
+ await waitFor(() => {
2273
+ rendered.getByText('test')
2274
+ })
2275
+
2276
+ expect(states[0]).toMatchObject({ data: undefined })
2277
+ expect(states[1]).toMatchObject({ data: 'test' })
2278
+
2279
+ // make sure no additional renders happen
2280
+ await sleep(50)
2281
+ expect(states.length).toBe(2)
2275
2282
  })
2276
- expect(states[1]).toMatchObject({
2277
- data: 'test',
2278
- status: 'success',
2279
- isFetching: false,
2283
+
2284
+ // See https://github.com/TanStack/query/discussions/5588
2285
+ describe('function', () => {
2286
+ it('should not re-render when it should only re-render on data changes and the data did not change', async () => {
2287
+ const key = queryKey()
2288
+ const states: UseQueryResult<string>[] = []
2289
+
2290
+ function Page() {
2291
+ const state = useQuery(
2292
+ key,
2293
+ async () => {
2294
+ await sleep(5)
2295
+ return 'test'
2296
+ },
2297
+ {
2298
+ notifyOnChangeProps: () => ['data'],
2299
+ },
2300
+ )
2301
+
2302
+ states.push(state)
2303
+
2304
+ return (
2305
+ <>
2306
+ <button
2307
+ onClick={async () => {
2308
+ await state.refetch()
2309
+ }}
2310
+ >
2311
+ refetch
2312
+ </button>
2313
+
2314
+ <div>{state.data}</div>
2315
+ </>
2316
+ )
2317
+ }
2318
+
2319
+ const rendered = renderWithClient(queryClient, <Page />)
2320
+
2321
+ await waitFor(() => {
2322
+ rendered.getByText('test')
2323
+ })
2324
+
2325
+ fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
2326
+
2327
+ // sleep is required to make sure no additional renders happen after click
2328
+ await sleep(20)
2329
+
2330
+ expect(states.length).toBe(2)
2331
+ expect(states[0]).toMatchObject({
2332
+ data: undefined,
2333
+ status: 'loading',
2334
+ isFetching: true,
2335
+ })
2336
+ expect(states[1]).toMatchObject({
2337
+ data: 'test',
2338
+ status: 'success',
2339
+ isFetching: false,
2340
+ })
2341
+ })
2342
+
2343
+ it('should not re-render when change props are not actively being tracked', async () => {
2344
+ const key = queryKey()
2345
+ const states: UseQueryResult<string>[] = []
2346
+
2347
+ function Page() {
2348
+ const fetchCounterRef = React.useRef(0)
2349
+ const trackChangesRef = React.useRef(true)
2350
+
2351
+ const notifyOnChangeProps = React.useCallback(() => {
2352
+ return trackChangesRef.current ? 'all' : []
2353
+ }, [])
2354
+
2355
+ const state = useQuery(
2356
+ key,
2357
+ async () => {
2358
+ await sleep(5)
2359
+ fetchCounterRef.current++
2360
+ return `fetch counter: ${fetchCounterRef.current}`
2361
+ },
2362
+ {
2363
+ notifyOnChangeProps,
2364
+ },
2365
+ )
2366
+
2367
+ states.push(state)
2368
+
2369
+ return (
2370
+ <>
2371
+ <button
2372
+ onClick={async () => {
2373
+ await state.refetch()
2374
+ }}
2375
+ >
2376
+ refetch
2377
+ </button>
2378
+ <button
2379
+ onClick={() => {
2380
+ trackChangesRef.current = true
2381
+ }}
2382
+ >
2383
+ enableTracking
2384
+ </button>
2385
+ <button
2386
+ onClick={() => {
2387
+ trackChangesRef.current = false
2388
+ }}
2389
+ >
2390
+ disableTracking
2391
+ </button>
2392
+
2393
+ <div>{state.data}</div>
2394
+ </>
2395
+ )
2396
+ }
2397
+
2398
+ const rendered = renderWithClient(queryClient, <Page />)
2399
+ await waitFor(() => {
2400
+ rendered.getByText('fetch counter: 1')
2401
+ })
2402
+
2403
+ expect(states.length).toBe(2)
2404
+ expect(states[0]).toMatchObject({
2405
+ data: undefined,
2406
+ isFetching: true,
2407
+ status: 'loading',
2408
+ })
2409
+ expect(states[1]).toMatchObject({
2410
+ data: 'fetch counter: 1',
2411
+ status: 'success',
2412
+ isFetching: false,
2413
+ })
2414
+
2415
+ // disable tracking and refetch to check for re-renders
2416
+ fireEvent.click(
2417
+ rendered.getByRole('button', { name: 'disableTracking' }),
2418
+ )
2419
+ fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
2420
+
2421
+ // sleep is required to make sure no additional renders happen after click
2422
+ await sleep(20)
2423
+ // still expect to only have two re-renders from the initial fetch
2424
+ expect(states.length).toBe(2)
2425
+
2426
+ // enable tracking and refetch to check for re-renders
2427
+ fireEvent.click(
2428
+ rendered.getByRole('button', { name: 'enableTracking' }),
2429
+ )
2430
+ fireEvent.click(rendered.getByRole('button', { name: 'refetch' }))
2431
+
2432
+ // sleep is required to make sure no additional renders happen after click
2433
+ await sleep(20)
2434
+
2435
+ expect(states.length).toBe(4)
2436
+ expect(states[2]).toMatchObject({
2437
+ data: 'fetch counter: 2',
2438
+ status: 'success',
2439
+ isFetching: true,
2440
+ })
2441
+ expect(states[3]).toMatchObject({
2442
+ data: 'fetch counter: 3',
2443
+ status: 'success',
2444
+ isFetching: false,
2445
+ })
2446
+ })
2280
2447
  })
2281
2448
  })
2282
2449
 
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react'
2
2
  import { act, render } from '@testing-library/react'
3
- import type { ContextOptions, QueryClientConfig, MutationOptions } from '..'
4
- import { QueryClient, QueryClientProvider } from '..'
5
3
  import * as utils from '@tanstack/query-core'
4
+ import { QueryClient, QueryClientProvider } from '..'
5
+ import type { ContextOptions, MutationOptions, QueryClientConfig } from '..'
6
6
 
7
7
  export function renderWithClient(
8
8
  client: QueryClient,
@@ -1,4 +1,6 @@
1
1
  'use client'
2
+ import * as React from 'react'
3
+ import { shouldThrowError } from './utils'
2
4
  import type {
3
5
  DefaultedQueryObserverOptions,
4
6
  Query,
@@ -7,8 +9,6 @@ import type {
7
9
  UseErrorBoundary,
8
10
  } from '@tanstack/query-core'
9
11
  import type { QueryErrorResetBoundaryValue } from './QueryErrorResetBoundary'
10
- import * as React from 'react'
11
- import { shouldThrowError } from './utils'
12
12
 
13
13
  export const ensurePreventErrorBoundaryRetry = <
14
14
  TQueryFnData,
@@ -1,4 +1,5 @@
1
1
  // @ts-ignore
2
2
  // eslint-disable-next-line import/no-unresolved
3
3
  import { unstable_batchedUpdates } from 'react-native'
4
+
4
5
  export { unstable_batchedUpdates }
@@ -1,3 +1,4 @@
1
1
  'use client'
2
2
  import * as ReactDOM from 'react-dom'
3
+
3
4
  export const unstable_batchedUpdates = ReactDOM.unstable_batchedUpdates
package/src/types.ts CHANGED
@@ -2,15 +2,15 @@
2
2
 
3
3
  import type * as React from 'react'
4
4
  import type {
5
+ DefinedQueryObserverResult,
5
6
  InfiniteQueryObserverOptions,
6
7
  InfiniteQueryObserverResult,
8
+ MutateFunction,
9
+ MutationObserverOptions,
7
10
  MutationObserverResult,
11
+ QueryKey,
8
12
  QueryObserverOptions,
9
13
  QueryObserverResult,
10
- QueryKey,
11
- MutationObserverOptions,
12
- MutateFunction,
13
- DefinedQueryObserverResult,
14
14
  } from '@tanstack/query-core'
15
15
  import type { QueryClient } from '@tanstack/query-core'
16
16
 
@@ -1,19 +1,19 @@
1
1
  'use client'
2
2
  import * as React from 'react'
3
- import { useSyncExternalStore } from './useSyncExternalStore'
4
3
 
5
- import type { QueryKey, QueryObserver } from '@tanstack/query-core'
6
4
  import { notifyManager } from '@tanstack/query-core'
5
+ import { useSyncExternalStore } from './useSyncExternalStore'
7
6
  import { useQueryErrorResetBoundary } from './QueryErrorResetBoundary'
8
7
  import { useQueryClient } from './QueryClientProvider'
9
- import type { UseBaseQueryOptions } from './types'
10
8
  import { useIsRestoring } from './isRestoring'
11
9
  import {
12
10
  ensurePreventErrorBoundaryRetry,
13
11
  getHasError,
14
12
  useClearResetErrorBoundary,
15
13
  } from './errorBoundaryUtils'
16
- import { ensureStaleTime, shouldSuspend, fetchOptimistic } from './suspense'
14
+ import { ensureStaleTime, fetchOptimistic, shouldSuspend } from './suspense'
15
+ import type { QueryKey, QueryObserver } from '@tanstack/query-core'
16
+ import type { UseBaseQueryOptions } from './types'
17
17
 
18
18
  export function useBaseQuery<
19
19
  TQueryFnData,