@tanstack/react-query 4.41.0 → 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.
- package/build/lib/Hydrate.d.ts +1 -1
- package/build/lib/QueryClientProvider.d.ts +1 -1
- package/build/lib/QueryClientProvider.esm.js.map +1 -1
- package/build/lib/QueryClientProvider.js.map +1 -1
- package/build/lib/QueryClientProvider.mjs.map +1 -1
- package/build/lib/QueryErrorResetBoundary.d.ts +1 -1
- package/build/lib/__tests__/utils.d.ts +2 -1
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +9 -7
- package/src/QueryClientProvider.tsx +1 -1
- package/src/__tests__/ssr-hydration.test.tsx +20 -7
- package/src/__tests__/suspense.test.tsx +18 -6
- package/src/__tests__/useMutation.test.tsx +3 -3
- package/src/__tests__/useQueries.test.tsx +164 -35
- package/src/__tests__/useQuery.test.tsx +3 -2
- package/src/__tests__/utils.tsx +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/react-query",
|
|
3
|
-
"version": "4.
|
|
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,13 +39,15 @@
|
|
|
39
39
|
],
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/jscodeshift": "^0.11.3",
|
|
42
|
-
"@types/react": "^
|
|
43
|
-
"@types/react-dom": "^
|
|
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": "^
|
|
45
|
+
"react": "^19.1.1",
|
|
46
46
|
"react-17": "npm:react@^17.0.2",
|
|
47
|
-
"react-
|
|
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
|
},
|
|
@@ -54,8 +56,8 @@
|
|
|
54
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": {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as React from 'react'
|
|
2
2
|
import ReactDOM from 'react-dom'
|
|
3
|
-
import
|
|
3
|
+
import { act } from '@testing-library/react'
|
|
4
4
|
import ReactDOMServer from 'react-dom/server'
|
|
5
|
-
|
|
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 || '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
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(() =>
|
|
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(() =>
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
749
|
-
return
|
|
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(() =>
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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()
|