diff --git a/.changeset/fix-svelte-use-mutation-state-shrink.md b/.changeset/fix-svelte-use-mutation-state-shrink.md new file mode 100644 index 00000000000..17bcb2996fb --- /dev/null +++ b/.changeset/fix-svelte-use-mutation-state-shrink.md @@ -0,0 +1,5 @@ +--- +"@tanstack/svelte-query": patch +--- + +fix(svelte-query): use splice in useMutationState so the result array shrinks when mutations no longer match the filter diff --git a/packages/svelte-query/src/useMutationState.svelte.ts b/packages/svelte-query/src/useMutationState.svelte.ts index b92c900e8cf..215956b7628 100644 --- a/packages/svelte-query/src/useMutationState.svelte.ts +++ b/packages/svelte-query/src/useMutationState.svelte.ts @@ -44,7 +44,7 @@ export function useMutationState< getResult(mutationCache, options), ) if (result !== nextResult) { - Object.assign(result, nextResult) + result.splice(0, result.length, ...nextResult) } }) diff --git a/packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts b/packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts index 703c05df631..77bb1134b5f 100644 --- a/packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts +++ b/packages/svelte-query/tests/useMutationState/useMutationState.svelte.test.ts @@ -157,3 +157,54 @@ describe('useMutationState', () => { expect(rendered.getByText('Data: ["success"]')).toBeInTheDocument() }) }) + +describe('useMutationState - array shrinks when mutations no longer match filter', () => { + let queryClient: QueryClient + + beforeEach(() => { + vi.useFakeTimers() + queryClient = new QueryClient() + }) + + afterEach(() => { + queryClient.clear() + vi.useRealTimers() + }) + + it('should remove mutations that no longer match the filter', async () => { + const firstKey = queryKey() + const secondKey = queryKey() + const mutationFn = vi.fn(() => sleep(10).then(() => 'data')) + + const rendered = render(Base, { + props: { + queryClient, + successMutationOpts: () => ({ + mutationKey: firstKey, + mutationFn, + }), + errorMutationOpts: () => ({ + mutationKey: secondKey, + mutationFn, + }), + mutationStateOpts: { + filters: { status: 'pending' }, + }, + }, + }) + + fireEvent.click(rendered.getByRole('button', { name: /Success/i })) + fireEvent.click(rendered.getByRole('button', { name: /Error/i })) + + await vi.advanceTimersByTimeAsync(0) + expect( + rendered.getByText('Data: ["pending","pending"]'), + ).toBeInTheDocument() + + await vi.advanceTimersByTimeAsync(10) + + // Both mutations settled — zero now match status: 'pending' + // Previously Object.assign never shrank the array so this stayed ["pending","pending"] + expect(rendered.getByText('Data: []')).toBeInTheDocument() + }) +})