diff --git a/packages/query-core/src/__tests__/queryClient.test.tsx b/packages/query-core/src/__tests__/queryClient.test.tsx index c09db304467..57b2b71faa4 100644 --- a/packages/query-core/src/__tests__/queryClient.test.tsx +++ b/packages/query-core/src/__tests__/queryClient.test.tsx @@ -1692,6 +1692,53 @@ describe('queryClient', () => { expect(queryFn2).toHaveBeenCalledTimes(0) expect(didSkipTokenRun).toBe(false) }) + + it('should refetch queries matched by a state-dependent predicate even though reset() mutates state', async () => { + const key1 = queryKey() + const key2 = queryKey() + const queryFn1 = vi + .fn<(...args: Array) => string>() + .mockReturnValue('data') + const queryFn2 = vi + .fn<(...args: Array) => string>() + .mockRejectedValue('error') + const observer1 = new QueryObserver(queryClient, { + queryKey: key1, + queryFn: queryFn1, + }) + const observer2 = new QueryObserver(queryClient, { + queryKey: key2, + queryFn: queryFn2, + retry: false, + }) + + observer1.subscribe(() => undefined) + observer2.subscribe(() => undefined) + + await vi.waitFor(() => { + expect(queryClient.getQueryState(key1)?.status).toBe('success') + expect(queryClient.getQueryState(key2)?.status).toBe('error') + }) + expect(queryFn1).toHaveBeenCalledTimes(1) + expect(queryFn2).toHaveBeenCalledTimes(1) + + await queryClient.resetQueries({ + predicate: (query) => query.state.status === 'success', + }) + + expect(queryFn1).toHaveBeenCalledTimes(2) + expect(queryFn2).toHaveBeenCalledTimes(1) + + await queryClient.resetQueries({ + predicate: (query) => query.state.status === 'error', + }) + + expect(queryFn1).toHaveBeenCalledTimes(2) + expect(queryFn2).toHaveBeenCalledTimes(2) + + observer1.destroy() + observer2.destroy() + }) }) describe('focusManager and onlineManager', () => { diff --git a/packages/query-core/src/queryClient.ts b/packages/query-core/src/queryClient.ts index 80cc36668aa..4c5cd5a2739 100644 --- a/packages/query-core/src/queryClient.ts +++ b/packages/query-core/src/queryClient.ts @@ -262,13 +262,15 @@ export class QueryClient { const queryCache = this.#queryCache return notifyManager.batch(() => { - queryCache.findAll(filters).forEach((query) => { + const matched = queryCache.findAll(filters) + const matchedHashes = new Set(matched.map((query) => query.queryHash)) + matched.forEach((query) => { query.reset() }) return this.refetchQueries( { type: 'active', - ...filters, + predicate: (query) => matchedHashes.has(query.queryHash), }, options, )