From c91c7201479a825863e141af891be65a84c0e665 Mon Sep 17 00:00:00 2001 From: Alex Liu Date: Mon, 2 Sep 2024 04:37:39 +0800 Subject: [PATCH] fix(vue-query): invalidate queries immediately after calling `invalidateQueries` (#7930) * fix(vue-query): invalidate queries immediately after call `invalidateQueries` * chore: recovery code comments --- .../src/__tests__/queryClient.test.ts | 55 ++++++++++++++++++- packages/vue-query/src/queryClient.ts | 34 ++++++++---- 2 files changed, 74 insertions(+), 15 deletions(-) diff --git a/packages/vue-query/src/__tests__/queryClient.test.ts b/packages/vue-query/src/__tests__/queryClient.test.ts index f875a59d54..45b508e5b1 100644 --- a/packages/vue-query/src/__tests__/queryClient.test.ts +++ b/packages/vue-query/src/__tests__/queryClient.test.ts @@ -188,7 +188,7 @@ describe('QueryCache', () => { }) describe('invalidateQueries', () => { - test('should properly unwrap 2 parameter', async () => { + test('should properly unwrap 2 parameter', () => { const queryClient = new QueryClient() queryClient.invalidateQueries( @@ -198,15 +198,64 @@ describe('QueryCache', () => { { cancelRefetch: ref(false) }, ) - await flushPromises() - expect(QueryClientOrigin.prototype.invalidateQueries).toBeCalledWith( { queryKey: queryKeyUnref, + refetchType: 'none', }, { cancelRefetch: false }, ) }) + + // #7694 + test('should call invalidateQueries immediately and refetchQueries after flushPromises', async () => { + const invalidateQueries = vi.spyOn( + QueryClientOrigin.prototype, + 'invalidateQueries', + ) + const refetchQueries = vi.spyOn( + QueryClientOrigin.prototype, + 'refetchQueries', + ) + + const queryClient = new QueryClient() + + queryClient.invalidateQueries({ + queryKey: queryKeyRef, + }) + + expect(invalidateQueries).toBeCalled() + expect(refetchQueries).not.toBeCalled() + + await flushPromises() + + expect(refetchQueries).toBeCalled() + }) + + test('should call invalidateQueries immediately and not call refetchQueries', async () => { + const invalidateQueries = vi.spyOn( + QueryClientOrigin.prototype, + 'invalidateQueries', + ) + const refetchQueries = vi.spyOn( + QueryClientOrigin.prototype, + 'refetchQueries', + ) + + const queryClient = new QueryClient() + + queryClient.invalidateQueries({ + queryKey: queryKeyRef, + refetchType: 'none', + }) + + expect(invalidateQueries).toBeCalled() + expect(refetchQueries).not.toBeCalled() + + await flushPromises() + + expect(refetchQueries).not.toBeCalled() + }) }) describe('refetchQueries', () => { diff --git a/packages/vue-query/src/queryClient.ts b/packages/vue-query/src/queryClient.ts index 281eca714a..eec781883d 100644 --- a/packages/vue-query/src/queryClient.ts +++ b/packages/vue-query/src/queryClient.ts @@ -1,4 +1,4 @@ -import { ref } from 'vue-demi' +import { nextTick, ref } from 'vue-demi' import { QueryClient as QC } from '@tanstack/query-core' import { cloneDeepUnref } from './utils' import { QueryCache } from './queryCache' @@ -174,17 +174,27 @@ export class QueryClient extends QC { filters: MaybeRefDeep = {}, options: MaybeRefDeep = {}, ): Promise { - // eslint-disable-next-line cspell/spellchecker - // (dosipiuk): We need to delay `invalidate` execution to next macro task for all reactive values to be updated. - // This ensures that `context` in `queryFn` while `invalidating` along reactive variable change has correct value. - return new Promise((resolve) => { - setTimeout(async () => { - await super.invalidateQueries( - cloneDeepUnref(filters), - cloneDeepUnref(options), - ) - resolve() - }, 0) + const filtersCloned = cloneDeepUnref(filters) + const optionsCloned = cloneDeepUnref(options) + + super.invalidateQueries( + { ...filtersCloned, refetchType: 'none' }, + optionsCloned, + ) + + if (filtersCloned.refetchType === 'none') { + return Promise.resolve() + } + + const refetchFilters: RefetchQueryFilters = { + ...filtersCloned, + type: filtersCloned.refetchType ?? filtersCloned.type ?? 'active', + } + + // (dosipiuk): We need to delay `refetchQueries` execution to next macro task for all reactive values to be updated. + // This ensures that `context` in `queryFn` while `invalidating` along reactive variable change has correct + return nextTick().then(() => { + return super.refetchQueries(refetchFilters, optionsCloned) }) }