Skip to content

Commit 75131d6

Browse files
gautemoTkDodo
andauthored
fix(core): do not update completed mutations (#7104)
* fix(core): do not update completed mutations * test(core): verify mutations meta in cache with multiple mutations * style(core): prettier formatting --------- Co-authored-by: Dominik Dorfmeister <[email protected]>
1 parent ee2112c commit 75131d6

File tree

2 files changed

+156
-2
lines changed

2 files changed

+156
-2
lines changed

packages/query-core/src/mutationObserver.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ export class MutationObserver<
7373
hashKey(prevOptions.mutationKey) !== hashKey(this.options.mutationKey)
7474
) {
7575
this.reset()
76-
} else {
77-
this.#currentMutation?.setOptions(this.options)
76+
} else if (this.#currentMutation?.state.status === 'pending') {
77+
this.#currentMutation.setOptions(this.options)
7878
}
7979
}
8080

packages/query-core/src/tests/mutationObserver.test.tsx

+154
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,158 @@ describe('mutationObserver', () => {
169169

170170
unsubscribe()
171171
})
172+
173+
test('changing mutation meta should not affect successful mutations', async () => {
174+
const mutationObserver = new MutationObserver(queryClient, {
175+
meta: { a: 1 },
176+
mutationFn: async (text: string) => {
177+
await sleep(5)
178+
return text
179+
},
180+
})
181+
182+
const subscriptionHandler = vi.fn()
183+
184+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
185+
186+
await mutationObserver.mutate('input')
187+
188+
expect(queryClient.getMutationCache().find({})).toMatchObject({
189+
options: { meta: { a: 1 } },
190+
state: {
191+
status: 'success',
192+
data: 'input',
193+
},
194+
})
195+
196+
mutationObserver.setOptions({
197+
meta: { a: 2 },
198+
})
199+
200+
expect(queryClient.getMutationCache().find({})).toMatchObject({
201+
options: { meta: { a: 1 } },
202+
state: {
203+
status: 'success',
204+
data: 'input',
205+
},
206+
})
207+
208+
unsubscribe()
209+
})
210+
211+
test('mutation cache should have different meta when updated between mutations', async () => {
212+
const mutationFn = async (text: string) => {
213+
await sleep(5)
214+
return text
215+
}
216+
const mutationObserver = new MutationObserver(queryClient, {
217+
meta: { a: 1 },
218+
mutationFn,
219+
})
220+
221+
const subscriptionHandler = vi.fn()
222+
223+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
224+
225+
await mutationObserver.mutate('input')
226+
227+
mutationObserver.setOptions({
228+
meta: { a: 2 },
229+
mutationFn,
230+
})
231+
232+
await mutationObserver.mutate('input')
233+
234+
const mutations = queryClient.getMutationCache().findAll()
235+
expect(mutations[0]).toMatchObject({
236+
options: { meta: { a: 1 } },
237+
state: {
238+
status: 'success',
239+
data: 'input',
240+
},
241+
})
242+
expect(mutations[1]).toMatchObject({
243+
options: { meta: { a: 2 } },
244+
state: {
245+
status: 'success',
246+
data: 'input',
247+
},
248+
})
249+
250+
unsubscribe()
251+
})
252+
253+
test('changing mutation meta should not affect rejected mutations', async () => {
254+
const mutationObserver = new MutationObserver(queryClient, {
255+
meta: { a: 1 },
256+
mutationFn: async (_: string) => {
257+
await sleep(5)
258+
return Promise.reject(new Error('err'))
259+
},
260+
})
261+
262+
const subscriptionHandler = vi.fn()
263+
264+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
265+
266+
await mutationObserver.mutate('input').catch(() => undefined)
267+
268+
expect(queryClient.getMutationCache().find({})).toMatchObject({
269+
options: { meta: { a: 1 } },
270+
state: {
271+
status: 'error',
272+
},
273+
})
274+
275+
mutationObserver.setOptions({
276+
meta: { a: 2 },
277+
})
278+
279+
expect(queryClient.getMutationCache().find({})).toMatchObject({
280+
options: { meta: { a: 1 } },
281+
state: {
282+
status: 'error',
283+
},
284+
})
285+
286+
unsubscribe()
287+
})
288+
289+
test('changing mutation meta should affect pending mutations', async () => {
290+
const mutationObserver = new MutationObserver(queryClient, {
291+
meta: { a: 1 },
292+
mutationFn: async (text: string) => {
293+
await sleep(20)
294+
return text
295+
},
296+
})
297+
298+
const subscriptionHandler = vi.fn()
299+
300+
const unsubscribe = mutationObserver.subscribe(subscriptionHandler)
301+
302+
mutationObserver.mutate('input')
303+
304+
await sleep(0)
305+
306+
expect(queryClient.getMutationCache().find({})).toMatchObject({
307+
options: { meta: { a: 1 } },
308+
state: {
309+
status: 'pending',
310+
},
311+
})
312+
313+
mutationObserver.setOptions({
314+
meta: { a: 2 },
315+
})
316+
317+
expect(queryClient.getMutationCache().find({})).toMatchObject({
318+
options: { meta: { a: 2 } },
319+
state: {
320+
status: 'pending',
321+
},
322+
})
323+
324+
unsubscribe()
325+
})
172326
})

0 commit comments

Comments
 (0)