diff --git a/packages/query-core/src/__tests__/queriesObserver.test.tsx b/packages/query-core/src/__tests__/queriesObserver.test.tsx index 0d0aa1224e..91317d9fe9 100644 --- a/packages/query-core/src/__tests__/queriesObserver.test.tsx +++ b/packages/query-core/src/__tests__/queriesObserver.test.tsx @@ -264,4 +264,72 @@ describe('queriesObserver', () => { // Clean-up unsubscribe2() }) + + test('should handle duplicate query keys in different positions', async () => { + const key1 = queryKey() + const key2 = queryKey() + const queryFn1 = vi.fn().mockReturnValue(1) + const queryFn2 = vi.fn().mockReturnValue(2) + + const observer = new QueriesObserver(queryClient, [ + { queryKey: key1, queryFn: queryFn1 }, + { queryKey: key2, queryFn: queryFn2 }, + { queryKey: key1, queryFn: queryFn1 }, + ]) + + const results: Array> = [] + results.push( + observer.getOptimisticResult( + [ + { queryKey: key1, queryFn: queryFn1 }, + { queryKey: key2, queryFn: queryFn2 }, + { queryKey: key1, queryFn: queryFn1 }, + ], + undefined, + )[0], + ) + + const unsubscribe = observer.subscribe((result) => { + results.push(result) + }) + + await sleep(1) + unsubscribe() + + expect(results.length).toBe(6) + expect(results[0]).toMatchObject([ + { status: 'pending', fetchStatus: 'idle', data: undefined }, + { status: 'pending', fetchStatus: 'idle', data: undefined }, + { status: 'pending', fetchStatus: 'idle', data: undefined }, + ]) + expect(results[1]).toMatchObject([ + { status: 'pending', fetchStatus: 'fetching', data: undefined }, + { status: 'pending', fetchStatus: 'idle', data: undefined }, + { status: 'pending', fetchStatus: 'idle', data: undefined }, + ]) + expect(results[2]).toMatchObject([ + { status: 'pending', fetchStatus: 'fetching', data: undefined }, + { status: 'pending', fetchStatus: 'fetching', data: undefined }, + { status: 'pending', fetchStatus: 'idle', data: undefined }, + ]) + expect(results[3]).toMatchObject([ + { status: 'success', fetchStatus: 'idle', data: 1 }, + { status: 'pending', fetchStatus: 'fetching', data: undefined }, + { status: 'pending', fetchStatus: 'idle', data: undefined }, + ]) + expect(results[4]).toMatchObject([ + { status: 'success', fetchStatus: 'idle', data: 1 }, + { status: 'pending', fetchStatus: 'fetching', data: undefined }, + { status: 'success', fetchStatus: 'idle', data: 1 }, + ]) + expect(results[5]).toMatchObject([ + { status: 'success', fetchStatus: 'idle', data: 1 }, + { status: 'success', fetchStatus: 'idle', data: 2 }, + { status: 'success', fetchStatus: 'idle', data: 1 }, + ]) + + // Verify that queryFn1 was only called once despite being used twice + expect(queryFn1).toHaveBeenCalledTimes(1) + expect(queryFn2).toHaveBeenCalledTimes(1) + }) }) diff --git a/packages/query-core/src/queriesObserver.ts b/packages/query-core/src/queriesObserver.ts index 600317ec29..b7433f5f7f 100644 --- a/packages/query-core/src/queriesObserver.ts +++ b/packages/query-core/src/queriesObserver.ts @@ -240,28 +240,14 @@ export class QueriesObserver< observer: match, }) } else { - const existingObserver = this.#observers.find( - (o) => o.options.queryHash === defaultedOptions.queryHash, - ) observers.push({ defaultedQueryOptions: defaultedOptions, - observer: - existingObserver ?? - new QueryObserver(this.#client, defaultedOptions), + observer: new QueryObserver(this.#client, defaultedOptions), }) } }) - return observers.sort((a, b) => { - return ( - queries.findIndex( - (q) => q.queryHash === a.defaultedQueryOptions.queryHash, - ) - - queries.findIndex( - (q) => q.queryHash === b.defaultedQueryOptions.queryHash, - ) - ) - }) + return observers } #onUpdate(observer: QueryObserver, result: QueryObserverResult): void {