@tanstack/query-core 4.25.0 → 4.26.1
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/mutation.d.ts +2 -0
- package/build/lib/mutation.esm.js +18 -9
- package/build/lib/mutation.esm.js.map +1 -1
- package/build/lib/mutation.js +18 -9
- package/build/lib/mutation.js.map +1 -1
- package/build/lib/mutation.mjs +18 -9
- package/build/lib/mutation.mjs.map +1 -1
- package/build/lib/mutationCache.d.ts +2 -1
- package/build/lib/mutationCache.esm.js.map +1 -1
- package/build/lib/mutationCache.js.map +1 -1
- package/build/lib/mutationCache.mjs.map +1 -1
- package/build/lib/mutationObserver.esm.js +6 -2
- package/build/lib/mutationObserver.esm.js.map +1 -1
- package/build/lib/mutationObserver.js +6 -2
- package/build/lib/mutationObserver.js.map +1 -1
- package/build/lib/mutationObserver.mjs +6 -2
- package/build/lib/mutationObserver.mjs.map +1 -1
- package/build/lib/query.esm.js +5 -3
- package/build/lib/query.esm.js.map +1 -1
- package/build/lib/query.js +5 -3
- package/build/lib/query.js.map +1 -1
- package/build/lib/query.mjs +5 -3
- package/build/lib/query.mjs.map +1 -1
- package/build/lib/queryCache.d.ts +1 -0
- package/build/lib/queryCache.esm.js.map +1 -1
- package/build/lib/queryCache.js.map +1 -1
- package/build/lib/queryCache.mjs.map +1 -1
- package/build/umd/index.development.js +29 -14
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +1 -1
- package/src/mutation.ts +30 -6
- package/src/mutationCache.ts +8 -1
- package/src/mutationObserver.ts +1 -0
- package/src/query.ts +10 -0
- package/src/queryCache.ts +5 -0
- package/src/tests/mutationCache.test.tsx +54 -10
- package/src/tests/mutations.test.tsx +31 -0
- package/src/tests/queryCache.test.tsx +18 -6
package/package.json
CHANGED
package/src/mutation.ts
CHANGED
|
@@ -89,10 +89,11 @@ export class Mutation<
|
|
|
89
89
|
TContext = unknown,
|
|
90
90
|
> extends Removable {
|
|
91
91
|
state: MutationState<TData, TError, TVariables, TContext>
|
|
92
|
-
options
|
|
92
|
+
options!: MutationOptions<TData, TError, TVariables, TContext>
|
|
93
93
|
mutationId: number
|
|
94
94
|
|
|
95
95
|
private observers: MutationObserver<TData, TError, TVariables, TContext>[]
|
|
96
|
+
private defaultOptions?: MutationOptions<TData, TError, TVariables, TContext>
|
|
96
97
|
private mutationCache: MutationCache
|
|
97
98
|
private logger: Logger
|
|
98
99
|
private retryer?: Retryer<TData>
|
|
@@ -100,20 +101,25 @@ export class Mutation<
|
|
|
100
101
|
constructor(config: MutationConfig<TData, TError, TVariables, TContext>) {
|
|
101
102
|
super()
|
|
102
103
|
|
|
103
|
-
this.
|
|
104
|
-
...config.defaultOptions,
|
|
105
|
-
...config.options,
|
|
106
|
-
}
|
|
104
|
+
this.defaultOptions = config.defaultOptions
|
|
107
105
|
this.mutationId = config.mutationId
|
|
108
106
|
this.mutationCache = config.mutationCache
|
|
109
107
|
this.logger = config.logger || defaultLogger
|
|
110
108
|
this.observers = []
|
|
111
109
|
this.state = config.state || getDefaultState()
|
|
112
110
|
|
|
113
|
-
this.
|
|
111
|
+
this.setOptions(config.options)
|
|
114
112
|
this.scheduleGc()
|
|
115
113
|
}
|
|
116
114
|
|
|
115
|
+
setOptions(
|
|
116
|
+
options?: MutationOptions<TData, TError, TVariables, TContext>,
|
|
117
|
+
): void {
|
|
118
|
+
this.options = { ...this.defaultOptions, ...options }
|
|
119
|
+
|
|
120
|
+
this.updateCacheTime(this.options.cacheTime)
|
|
121
|
+
}
|
|
122
|
+
|
|
117
123
|
get meta(): MutationMeta | undefined {
|
|
118
124
|
return this.options.meta
|
|
119
125
|
}
|
|
@@ -223,6 +229,15 @@ export class Mutation<
|
|
|
223
229
|
this.state.context!,
|
|
224
230
|
)
|
|
225
231
|
|
|
232
|
+
// Notify cache callback
|
|
233
|
+
await this.mutationCache.config.onSettled?.(
|
|
234
|
+
data,
|
|
235
|
+
null,
|
|
236
|
+
this.state.variables,
|
|
237
|
+
this.state.context,
|
|
238
|
+
this as Mutation<unknown, unknown, unknown, unknown>,
|
|
239
|
+
)
|
|
240
|
+
|
|
226
241
|
await this.options.onSettled?.(
|
|
227
242
|
data,
|
|
228
243
|
null,
|
|
@@ -252,6 +267,15 @@ export class Mutation<
|
|
|
252
267
|
this.state.context,
|
|
253
268
|
)
|
|
254
269
|
|
|
270
|
+
// Notify cache callback
|
|
271
|
+
await this.mutationCache.config.onSettled?.(
|
|
272
|
+
undefined,
|
|
273
|
+
error,
|
|
274
|
+
this.state.variables,
|
|
275
|
+
this.state.context,
|
|
276
|
+
this as Mutation<unknown, unknown, unknown, unknown>,
|
|
277
|
+
)
|
|
278
|
+
|
|
255
279
|
await this.options.onSettled?.(
|
|
256
280
|
undefined,
|
|
257
281
|
error as TError,
|
package/src/mutationCache.ts
CHANGED
|
@@ -25,7 +25,14 @@ interface MutationCacheConfig {
|
|
|
25
25
|
) => Promise<unknown> | unknown
|
|
26
26
|
onMutate?: (
|
|
27
27
|
variables: unknown,
|
|
28
|
-
mutation: Mutation<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/mutationObserver.ts
CHANGED
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
|
|
7
|
-
test('should
|
|
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
|
|
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
|
|
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
|
|
54
|
-
test('should
|
|
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
|
|
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
|
|
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', () => {
|
|
@@ -2,6 +2,7 @@ import type { QueryClient } from '..'
|
|
|
2
2
|
import { createQueryClient, executeMutation, queryKey, sleep } from './utils'
|
|
3
3
|
import type { MutationState } from '../mutation'
|
|
4
4
|
import { MutationObserver } from '../mutationObserver'
|
|
5
|
+
import { waitFor } from '@testing-library/react'
|
|
5
6
|
|
|
6
7
|
describe('mutations', () => {
|
|
7
8
|
let queryClient: QueryClient
|
|
@@ -358,4 +359,34 @@ describe('mutations', () => {
|
|
|
358
359
|
expect(onSuccess).not.toHaveBeenCalled()
|
|
359
360
|
expect(onSettled).not.toHaveBeenCalled()
|
|
360
361
|
})
|
|
362
|
+
|
|
363
|
+
test('mutation callbacks should see updated options', async () => {
|
|
364
|
+
const onSuccess = jest.fn()
|
|
365
|
+
|
|
366
|
+
const mutation = new MutationObserver(queryClient, {
|
|
367
|
+
mutationFn: async () => {
|
|
368
|
+
sleep(100)
|
|
369
|
+
return 'update'
|
|
370
|
+
},
|
|
371
|
+
onSuccess: () => {
|
|
372
|
+
onSuccess(1)
|
|
373
|
+
},
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
void mutation.mutate()
|
|
377
|
+
|
|
378
|
+
mutation.setOptions({
|
|
379
|
+
mutationFn: async () => {
|
|
380
|
+
sleep(100)
|
|
381
|
+
return 'update'
|
|
382
|
+
},
|
|
383
|
+
onSuccess: () => {
|
|
384
|
+
onSuccess(2)
|
|
385
|
+
},
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
await waitFor(() => expect(onSuccess).toHaveBeenCalledTimes(1))
|
|
389
|
+
|
|
390
|
+
expect(onSuccess).toHaveBeenCalledWith(2)
|
|
391
|
+
})
|
|
361
392
|
})
|
|
@@ -205,29 +205,41 @@ describe('queryCache', () => {
|
|
|
205
205
|
})
|
|
206
206
|
})
|
|
207
207
|
|
|
208
|
-
describe('QueryCacheConfig
|
|
209
|
-
test('should
|
|
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
|
|
223
|
-
test('should
|
|
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
|
|
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
|
|