diff --git a/.changeset/green-peaches-yawn.md b/.changeset/green-peaches-yawn.md new file mode 100644 index 00000000000..e85f75465ad --- /dev/null +++ b/.changeset/green-peaches-yawn.md @@ -0,0 +1,5 @@ +--- +'@tanstack/svelte-query': patch +--- + +Fix `createQueries` when a reactive query list removes multiple items in one update. diff --git a/packages/svelte-query/src/containers.svelte.ts b/packages/svelte-query/src/containers.svelte.ts index 60d27c68431..8a812d566f2 100644 --- a/packages/svelte-query/src/containers.svelte.ts +++ b/packages/svelte-query/src/containers.svelte.ts @@ -84,11 +84,17 @@ export function createRawRef>( }, }) + /** + * Replaces the proxy-backed top-level keys in place while preserving the original reference. + */ function update(newValue: T) { const existingKeys = Object.keys(out) const newKeys = Object.keys(newValue) const keysToRemove = existingKeys.filter((key) => !newKeys.includes(key)) - for (const key of keysToRemove) { + const keysToDelete = Array.isArray(out) + ? [...keysToRemove].reverse() + : keysToRemove + for (const key of keysToDelete) { // @ts-expect-error delete out[key] } diff --git a/packages/svelte-query/tests/createQueries.svelte.test.ts b/packages/svelte-query/tests/createQueries.svelte.test.ts index c648942483c..ea61a9b37f9 100644 --- a/packages/svelte-query/tests/createQueries.svelte.test.ts +++ b/packages/svelte-query/tests/createQueries.svelte.test.ts @@ -1,6 +1,10 @@ import { afterEach, describe, expect, expectTypeOf, it, vi } from 'vitest' import { QueryClient, createQueries } from '../src/index.js' -import { promiseWithResolvers, withEffectRoot } from './utils.svelte.js' +import { + promiseWithResolvers, + ref, + withEffectRoot, +} from './utils.svelte.js' import type { CreateQueryOptions, CreateQueryResult, @@ -827,6 +831,32 @@ describe('createQueries', () => { }), ) + it( + 'should handle removing multiple queries in a single update', + withEffectRoot(async () => { + const filters = ref([1, 2, 3, 4]) + + const results = createQueries( + () => ({ + queries: filters.value.map((filter) => ({ + queryKey: ['filter', filter], + queryFn: () => filter, + })), + }), + () => queryClient, + ) + + await vi.waitFor(() => + expect(results.map((result) => result.data)).toEqual([1, 2, 3, 4]), + ) + + filters.value = filters.value.slice(0, 2) + + await vi.waitFor(() => expect(results).toHaveLength(2)) + expect(results.map((result) => result.data)).toEqual([1, 2]) + }), + ) + it( 'should track property access through combine function', withEffectRoot(async () => {