@tanstack/query-core 4.24.10 → 4.26.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/query-core",
3
- "version": "4.24.10",
3
+ "version": "4.26.0",
4
4
  "description": "The framework agnostic core that powers TanStack Query",
5
5
  "author": "tannerlinsley",
6
6
  "license": "MIT",
package/src/index.ts CHANGED
@@ -16,6 +16,7 @@ export {
16
16
  replaceEqualDeep,
17
17
  isError,
18
18
  isServer,
19
+ matchQuery,
19
20
  parseQueryArgs,
20
21
  parseFilterArgs,
21
22
  parseMutationFilterArgs,
package/src/mutation.ts CHANGED
@@ -223,6 +223,15 @@ export class Mutation<
223
223
  this.state.context!,
224
224
  )
225
225
 
226
+ // Notify cache callback
227
+ await this.mutationCache.config.onSettled?.(
228
+ data,
229
+ null,
230
+ this.state.variables,
231
+ this.state.context,
232
+ this as Mutation<unknown, unknown, unknown, unknown>,
233
+ )
234
+
226
235
  await this.options.onSettled?.(
227
236
  data,
228
237
  null,
@@ -252,6 +261,15 @@ export class Mutation<
252
261
  this.state.context,
253
262
  )
254
263
 
264
+ // Notify cache callback
265
+ await this.mutationCache.config.onSettled?.(
266
+ undefined,
267
+ error,
268
+ this.state.variables,
269
+ this.state.context,
270
+ this as Mutation<unknown, unknown, unknown, unknown>,
271
+ )
272
+
255
273
  await this.options.onSettled?.(
256
274
  undefined,
257
275
  error as TError,
@@ -25,7 +25,14 @@ interface MutationCacheConfig {
25
25
  ) => Promise<unknown> | unknown
26
26
  onMutate?: (
27
27
  variables: unknown,
28
- mutation: Mutation<unknown, unknown, unknown, unknown>,
28
+ mutation: Mutation<unknown, unknown, unknown>,
29
+ ) => Promise<unknown> | unknown
30
+ onSettled?: (
31
+ data: unknown | undefined,
32
+ error: unknown | null,
33
+ variables: unknown,
34
+ context: unknown,
35
+ mutation: Mutation<unknown, unknown, unknown>,
29
36
  ) => Promise<unknown> | unknown
30
37
  }
31
38
 
package/src/query.ts CHANGED
@@ -434,6 +434,11 @@ export class Query<
434
434
  if (!isCancelledError(error)) {
435
435
  // Notify cache callback
436
436
  this.cache.config.onError?.(error, this as Query<any, any, any, any>)
437
+ this.cache.config.onSettled?.(
438
+ this.state.data,
439
+ error,
440
+ this as Query<any, any, any, any>,
441
+ )
437
442
 
438
443
  if (process.env.NODE_ENV !== 'production') {
439
444
  this.logger.error(error)
@@ -466,6 +471,11 @@ export class Query<
466
471
 
467
472
  // Notify cache callback
468
473
  this.cache.config.onSuccess?.(data, this as Query<any, any, any, any>)
474
+ this.cache.config.onSettled?.(
475
+ data,
476
+ this.state.error,
477
+ this as Query<any, any, any, any>,
478
+ )
469
479
 
470
480
  if (!this.isFetchingOptimistic) {
471
481
  // Schedule query gc after fetching
package/src/queryCache.ts CHANGED
@@ -13,6 +13,11 @@ import type { QueryObserver } from './queryObserver'
13
13
  interface QueryCacheConfig {
14
14
  onError?: (error: unknown, query: Query<unknown, unknown, unknown>) => void
15
15
  onSuccess?: (data: unknown, query: Query<unknown, unknown, unknown>) => void
16
+ onSettled?: (
17
+ data: unknown | undefined,
18
+ error: unknown | null,
19
+ query: Query<unknown, unknown, unknown>,
20
+ ) => void
16
21
  }
17
22
 
18
23
  interface QueryHashMap {
@@ -3,11 +3,13 @@ import { queryKey, sleep, executeMutation, createQueryClient } from './utils'
3
3
  import { MutationCache, MutationObserver } from '..'
4
4
 
5
5
  describe('mutationCache', () => {
6
- describe('MutationCacheConfig.onError', () => {
7
- test('should be called when a mutation errors', async () => {
6
+ describe('MutationCacheConfig error callbacks', () => {
7
+ test('should call onError and onSettled when a mutation errors', async () => {
8
8
  const key = queryKey()
9
9
  const onError = jest.fn()
10
- const testCache = new MutationCache({ onError })
10
+ const onSuccess = jest.fn()
11
+ const onSettled = jest.fn()
12
+ const testCache = new MutationCache({ onError, onSuccess, onSettled })
11
13
  const testClient = createQueryClient({ mutationCache: testCache })
12
14
 
13
15
  try {
@@ -20,7 +22,17 @@ describe('mutationCache', () => {
20
22
  } catch {}
21
23
 
22
24
  const mutation = testCache.getAll()[0]
25
+ expect(onError).toHaveBeenCalledTimes(1)
23
26
  expect(onError).toHaveBeenCalledWith('error', 'vars', 'context', mutation)
27
+ expect(onSuccess).not.toHaveBeenCalled()
28
+ expect(onSettled).toHaveBeenCalledTimes(1)
29
+ expect(onSettled).toHaveBeenCalledWith(
30
+ undefined,
31
+ 'error',
32
+ 'vars',
33
+ 'context',
34
+ mutation,
35
+ )
24
36
  })
25
37
 
26
38
  test('should be awaited', async () => {
@@ -31,7 +43,12 @@ describe('mutationCache', () => {
31
43
  await sleep(1)
32
44
  states.push(2)
33
45
  }
34
- const testCache = new MutationCache({ onError })
46
+ const onSettled = async () => {
47
+ states.push(5)
48
+ await sleep(1)
49
+ states.push(6)
50
+ }
51
+ const testCache = new MutationCache({ onError, onSettled })
35
52
  const testClient = createQueryClient({ mutationCache: testCache })
36
53
 
37
54
  try {
@@ -44,17 +61,24 @@ describe('mutationCache', () => {
44
61
  await sleep(1)
45
62
  states.push(4)
46
63
  },
64
+ onSettled: async () => {
65
+ states.push(7)
66
+ await sleep(1)
67
+ states.push(8)
68
+ },
47
69
  })
48
70
  } catch {}
49
71
 
50
- expect(states).toEqual([1, 2, 3, 4])
72
+ expect(states).toEqual([1, 2, 3, 4, 5, 6, 7, 8])
51
73
  })
52
74
  })
53
- describe('MutationCacheConfig.onSuccess', () => {
54
- test('should be called when a mutation is successful', async () => {
75
+ describe('MutationCacheConfig success callbacks', () => {
76
+ test('should call onSuccess and onSettled when a mutation is successful', async () => {
55
77
  const key = queryKey()
78
+ const onError = jest.fn()
56
79
  const onSuccess = jest.fn()
57
- const testCache = new MutationCache({ onSuccess })
80
+ const onSettled = jest.fn()
81
+ const testCache = new MutationCache({ onError, onSuccess, onSettled })
58
82
  const testClient = createQueryClient({ mutationCache: testCache })
59
83
 
60
84
  try {
@@ -67,12 +91,22 @@ describe('mutationCache', () => {
67
91
  } catch {}
68
92
 
69
93
  const mutation = testCache.getAll()[0]
94
+ expect(onSuccess).toHaveBeenCalledTimes(1)
70
95
  expect(onSuccess).toHaveBeenCalledWith(
71
96
  { data: 5 },
72
97
  'vars',
73
98
  'context',
74
99
  mutation,
75
100
  )
101
+ expect(onError).not.toHaveBeenCalled()
102
+ expect(onSettled).toHaveBeenCalledTimes(1)
103
+ expect(onSettled).toHaveBeenCalledWith(
104
+ { data: 5 },
105
+ null,
106
+ 'vars',
107
+ 'context',
108
+ mutation,
109
+ )
76
110
  })
77
111
  test('should be awaited', async () => {
78
112
  const key = queryKey()
@@ -82,7 +116,12 @@ describe('mutationCache', () => {
82
116
  await sleep(1)
83
117
  states.push(2)
84
118
  }
85
- const testCache = new MutationCache({ onSuccess })
119
+ const onSettled = async () => {
120
+ states.push(5)
121
+ await sleep(1)
122
+ states.push(6)
123
+ }
124
+ const testCache = new MutationCache({ onSuccess, onSettled })
86
125
  const testClient = createQueryClient({ mutationCache: testCache })
87
126
 
88
127
  await executeMutation(testClient, {
@@ -94,9 +133,14 @@ describe('mutationCache', () => {
94
133
  await sleep(1)
95
134
  states.push(4)
96
135
  },
136
+ onSettled: async () => {
137
+ states.push(7)
138
+ await sleep(1)
139
+ states.push(8)
140
+ },
97
141
  })
98
142
 
99
- expect(states).toEqual([1, 2, 3, 4])
143
+ expect(states).toEqual([1, 2, 3, 4, 5, 6, 7, 8])
100
144
  })
101
145
  })
102
146
  describe('MutationCacheConfig.onMutate', () => {
@@ -205,29 +205,41 @@ describe('queryCache', () => {
205
205
  })
206
206
  })
207
207
 
208
- describe('QueryCacheConfig.onError', () => {
209
- test('should be called when a query errors', async () => {
208
+ describe('QueryCacheConfig error callbacks', () => {
209
+ test('should call onError and onSettled when a query errors', async () => {
210
210
  const key = queryKey()
211
+ const onSuccess = jest.fn()
212
+ const onSettled = jest.fn()
211
213
  const onError = jest.fn()
212
- const testCache = new QueryCache({ onError })
214
+ const testCache = new QueryCache({ onSuccess, onError, onSettled })
213
215
  const testClient = createQueryClient({ queryCache: testCache })
214
216
  await testClient.prefetchQuery(key, () =>
215
217
  Promise.reject<unknown>('error'),
216
218
  )
217
219
  const query = testCache.find(key)
220
+ expect(onError).toHaveBeenCalledTimes(1)
218
221
  expect(onError).toHaveBeenCalledWith('error', query)
222
+ expect(onSuccess).not.toHaveBeenCalled()
223
+ expect(onSettled).toHaveBeenCalledTimes(1)
224
+ expect(onSettled).toHaveBeenCalledWith(undefined, 'error', query)
219
225
  })
220
226
  })
221
227
 
222
- describe('QueryCacheConfig.onSuccess', () => {
223
- test('should be called when a query is successful', async () => {
228
+ describe('QueryCacheConfig success callbacks', () => {
229
+ test('should call onSuccess and onSettled when a query is successful', async () => {
224
230
  const key = queryKey()
225
231
  const onSuccess = jest.fn()
226
- const testCache = new QueryCache({ onSuccess })
232
+ const onSettled = jest.fn()
233
+ const onError = jest.fn()
234
+ const testCache = new QueryCache({ onSuccess, onError, onSettled })
227
235
  const testClient = createQueryClient({ queryCache: testCache })
228
236
  await testClient.prefetchQuery(key, () => Promise.resolve({ data: 5 }))
229
237
  const query = testCache.find(key)
238
+ expect(onSuccess).toHaveBeenCalledTimes(1)
230
239
  expect(onSuccess).toHaveBeenCalledWith({ data: 5 }, query)
240
+ expect(onError).not.toHaveBeenCalled()
241
+ expect(onSettled).toHaveBeenCalledTimes(1)
242
+ expect(onSettled).toHaveBeenCalledWith({ data: 5 }, null, query)
231
243
  })
232
244
  })
233
245