@tanstack/react-query 4.22.0 → 4.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/react-query",
3
- "version": "4.22.0",
3
+ "version": "4.22.4",
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.22.0"
50
+ "@tanstack/query-core": "4.22.4"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
@@ -63,10 +63,12 @@
63
63
  }
64
64
  },
65
65
  "scripts": {
66
- "clean": "rm -rf ./build",
67
- "test:codemods": "../../node_modules/.bin/jest --config codemods/jest.config.js",
68
- "test:eslint": "../../node_modules/.bin/eslint --ext .ts,.tsx ./src",
69
- "test:jest": "pnpm run test:codemods && ../../node_modules/.bin/jest --config ./jest.config.ts",
70
- "test:dev": "pnpm run test:jest --watch"
66
+ "clean": "rimraf ./build",
67
+ "test:eslint": "eslint --ext .ts,.tsx ./src",
68
+ "test:types": "tsc",
69
+ "test:lib": "jest --config ./jest.config.ts",
70
+ "test:lib:dev": "pnpm run test:lib --watch",
71
+ "test:lib:publish": "pnpm run test:lib --collectCoverage false",
72
+ "build:types": "tsc --build"
71
73
  }
72
74
  }
@@ -151,7 +151,7 @@ describe("useQuery's in Suspense mode", () => {
151
151
  useQuery(
152
152
  key,
153
153
  () => {
154
- sleep(10)
154
+ sleep(50)
155
155
  return 'data'
156
156
  },
157
157
  { suspense: true },
@@ -1084,7 +1084,7 @@ describe('useQueries with suspense', () => {
1084
1084
  queryKey: key1,
1085
1085
  queryFn: async () => {
1086
1086
  results.push('1')
1087
- await sleep(10)
1087
+ await sleep(50)
1088
1088
  return '1'
1089
1089
  },
1090
1090
  suspense: true,
@@ -1093,7 +1093,7 @@ describe('useQueries with suspense', () => {
1093
1093
  queryKey: key2,
1094
1094
  queryFn: async () => {
1095
1095
  results.push('2')
1096
- await sleep(20)
1096
+ await sleep(200)
1097
1097
  return '2'
1098
1098
  },
1099
1099
  staleTime: 1000,
@@ -1101,6 +1101,7 @@ describe('useQueries with suspense', () => {
1101
1101
  },
1102
1102
  ],
1103
1103
  })
1104
+
1104
1105
  return (
1105
1106
  <div>
1106
1107
  <h1>data: {result.map((it) => it.data ?? 'null').join(',')}</h1>
@@ -283,12 +283,15 @@ describe('useInfiniteQuery', () => {
283
283
  }),
284
284
  })
285
285
  states.push(state)
286
- return null
286
+
287
+ return <div>{state.data?.pages.join(',')}</div>
287
288
  }
288
289
 
289
- renderWithClient(queryClient, <Page />)
290
+ const rendered = renderWithClient(queryClient, <Page />)
290
291
 
291
- await sleep(10)
292
+ await waitFor(() => {
293
+ rendered.getByText('count: 1')
294
+ })
292
295
 
293
296
  expect(states.length).toBe(2)
294
297
  expect(states[0]).toMatchObject({
@@ -317,12 +320,21 @@ describe('useInfiniteQuery', () => {
317
320
  }, []),
318
321
  })
319
322
  states.push(state)
320
- return null
323
+
324
+ return (
325
+ <div>
326
+ {state.data?.pages.map((page) => (
327
+ <div key={page.id}>count: {page.count}</div>
328
+ ))}
329
+ </div>
330
+ )
321
331
  }
322
332
 
323
- renderWithClient(queryClient, <Page />)
333
+ const rendered = renderWithClient(queryClient, <Page />)
324
334
 
325
- await sleep(20)
335
+ await waitFor(() => {
336
+ rendered.getByText('count: 1')
337
+ })
326
338
 
327
339
  expect(states.length).toBe(2)
328
340
  expect(selectCalled).toBe(1)
@@ -415,20 +427,29 @@ describe('useInfiniteQuery', () => {
415
427
 
416
428
  states.push(state)
417
429
 
418
- const { fetchPreviousPage } = state
430
+ return (
431
+ <div>
432
+ <div>data: {state.data?.pages.join(',') ?? null}</div>
433
+ <button onClick={() => state.fetchPreviousPage()}>
434
+ fetch previous page
435
+ </button>
436
+ </div>
437
+ )
438
+ }
419
439
 
420
- React.useEffect(() => {
421
- setActTimeout(() => {
422
- fetchPreviousPage()
423
- }, 20)
424
- }, [fetchPreviousPage])
440
+ const rendered = renderWithClient(queryClient, <Page />)
425
441
 
426
- return null
427
- }
442
+ await waitFor(() => {
443
+ rendered.getByText('data: 10')
444
+ })
428
445
 
429
- renderWithClient(queryClient, <Page />)
446
+ fireEvent.click(
447
+ rendered.getByRole('button', { name: /fetch previous page/i }),
448
+ )
430
449
 
431
- await sleep(100)
450
+ await waitFor(() => {
451
+ rendered.getByText('data: 9,10')
452
+ })
432
453
 
433
454
  expect(states.length).toBe(4)
434
455
  expect(states[0]).toMatchObject({
@@ -1044,7 +1044,7 @@ describe('useMutation', () => {
1044
1044
  )
1045
1045
  })
1046
1046
 
1047
- test('should go to error state if onSuccess callback errors', async () => {
1047
+ it('should go to error state if onSuccess callback errors', async () => {
1048
1048
  const error = new Error('error from onSuccess')
1049
1049
  const onError = jest.fn()
1050
1050
 
@@ -1079,7 +1079,7 @@ describe('useMutation', () => {
1079
1079
  expect(onError).toHaveBeenCalledWith(error, 'todo', undefined)
1080
1080
  })
1081
1081
 
1082
- test('should go to error state if onError callback errors', async () => {
1082
+ it('should go to error state if onError callback errors', async () => {
1083
1083
  const error = new Error('error from onError')
1084
1084
  const mutateFnError = new Error('mutateFnError')
1085
1085
 
@@ -1115,7 +1115,7 @@ describe('useMutation', () => {
1115
1115
  await rendered.findByText('error: mutateFnError, status: error')
1116
1116
  })
1117
1117
 
1118
- test('should go to error state if onSettled callback errors', async () => {
1118
+ it('should go to error state if onSettled callback errors', async () => {
1119
1119
  const error = new Error('error from onSettled')
1120
1120
  const mutateFnError = new Error('mutateFnError')
1121
1121
  const onError = jest.fn()
@@ -1154,4 +1154,60 @@ describe('useMutation', () => {
1154
1154
 
1155
1155
  expect(onError).toHaveBeenCalledWith(mutateFnError, 'todo', undefined)
1156
1156
  })
1157
+
1158
+ it('should not call mutate callbacks for mutations started after unmount', async () => {
1159
+ const onSuccessMutate = jest.fn()
1160
+ const onSuccessUseMutation = jest.fn()
1161
+ const onSettledMutate = jest.fn()
1162
+ const onSettledUseMutation = jest.fn()
1163
+
1164
+ function Page() {
1165
+ const [show, setShow] = React.useState(true)
1166
+ return (
1167
+ <div>
1168
+ <button onClick={() => setShow(false)}>hide</button>
1169
+ {show && <Component />}
1170
+ </div>
1171
+ )
1172
+ }
1173
+
1174
+ function Component() {
1175
+ const mutation = useMutation({
1176
+ mutationFn: async (text: string) => {
1177
+ await sleep(10)
1178
+ return text
1179
+ },
1180
+ onSuccess: onSuccessUseMutation,
1181
+ onSettled: onSettledUseMutation,
1182
+ })
1183
+
1184
+ return (
1185
+ <div>
1186
+ <button
1187
+ onClick={() => {
1188
+ setActTimeout(() => {
1189
+ mutation.mutate('todo', {
1190
+ onSuccess: onSuccessMutate,
1191
+ onSettled: onSettledMutate,
1192
+ })
1193
+ }, 10)
1194
+ }}
1195
+ >
1196
+ mutate
1197
+ </button>
1198
+ </div>
1199
+ )
1200
+ }
1201
+
1202
+ const rendered = renderWithClient(queryClient, <Page />)
1203
+
1204
+ fireEvent.click(rendered.getByRole('button', { name: /mutate/i }))
1205
+ fireEvent.click(rendered.getByRole('button', { name: /hide/i }))
1206
+
1207
+ await waitFor(() => expect(onSuccessUseMutation).toHaveBeenCalledTimes(1))
1208
+ await waitFor(() => expect(onSettledUseMutation).toHaveBeenCalledTimes(1))
1209
+
1210
+ expect(onSuccessMutate).toHaveBeenCalledTimes(0)
1211
+ expect(onSettledMutate).toHaveBeenCalledTimes(0)
1212
+ })
1157
1213
  })
@@ -45,7 +45,7 @@ describe('useQueries', () => {
45
45
  {
46
46
  queryKey: key2,
47
47
  queryFn: async () => {
48
- await sleep(100)
48
+ await sleep(200)
49
49
  return 2
50
50
  },
51
51
  },
@@ -1050,12 +1050,21 @@ describe('useQueries', () => {
1050
1050
  ],
1051
1051
  })
1052
1052
  results.push(result)
1053
- return null
1053
+
1054
+ return (
1055
+ <div>
1056
+ <div>data1: {result[0].data}</div>
1057
+ <div>data2: {result[1].data}</div>
1058
+ </div>
1059
+ )
1054
1060
  }
1055
1061
 
1056
- renderWithClient(queryClient, <Page />, { context })
1062
+ const rendered = renderWithClient(queryClient, <Page />, { context })
1057
1063
 
1058
- await sleep(30)
1064
+ await waitFor(() => {
1065
+ rendered.getByText('data1: 1')
1066
+ rendered.getByText('data2: 2')
1067
+ })
1059
1068
 
1060
1069
  expect(results[0]).toMatchObject([
1061
1070
  { data: undefined },