Skip to content

Commit

Permalink
fix(vue-query): invalidate queries immediately after calling `invalid…
Browse files Browse the repository at this point in the history
…ateQueries` (#7930)

* fix(vue-query): invalidate queries immediately after call `invalidateQueries`

* chore: recovery code comments
  • Loading branch information
Mini-ghost authored Sep 1, 2024
1 parent 4977296 commit c91c720
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 15 deletions.
55 changes: 52 additions & 3 deletions packages/vue-query/src/__tests__/queryClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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', () => {
Expand Down
34 changes: 22 additions & 12 deletions packages/vue-query/src/queryClient.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand Down Expand Up @@ -174,17 +174,27 @@ export class QueryClient extends QC {
filters: MaybeRefDeep<InvalidateQueryFilters> = {},
options: MaybeRefDeep<InvalidateOptions> = {},
): Promise<void> {
// 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)
})
}

Expand Down

0 comments on commit c91c720

Please sign in to comment.