Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/curvy-webs-create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/vue-query': minor
---

feat(vue-query): allow options getters in additional composables
6 changes: 3 additions & 3 deletions packages/vue-query/src/__mocks__/useBaseQuery.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { vi } from 'vitest'
import type { Mock } from 'vitest'

const { useBaseQuery: originImpl, unrefQueryArgs: originalParse } =
(await vi.importActual('../useBaseQuery')) as any
const { useBaseQuery: originImpl } = (await vi.importActual(
'../useBaseQuery',
)) as any

export const useBaseQuery: Mock<(...args: Array<any>) => any> =
vi.fn(originImpl)
export const unrefQueryArgs = originalParse
2 changes: 1 addition & 1 deletion packages/vue-query/src/__tests__/useInfiniteQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { infiniteQueryOptions } from '../infiniteQueryOptions'

vi.mock('../useQueryClient')

describe('useQuery', () => {
describe('useInfiniteQuery', () => {
beforeEach(() => {
vi.useFakeTimers()
})
Expand Down
32 changes: 23 additions & 9 deletions packages/vue-query/src/__tests__/useIsFetching.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
import { onScopeDispose, reactive } from 'vue-demi'
import { onScopeDispose, reactive, ref } from 'vue-demi'
import { sleep } from '@tanstack/query-test-utils'
import { useQuery } from '../useQuery'
import { useIsFetching } from '../useIsFetching'
Expand Down Expand Up @@ -65,15 +65,10 @@ describe('useIsFetching', () => {
})

test('should properly update filters', async () => {
const filter = reactive({ stale: false })
const filter = reactive({ stale: false, queryKey: ['isFetchingFilter'] })
useQuery({
queryKey: ['isFetching'],
queryFn: () =>
new Promise((resolve) => {
setTimeout(() => {
return resolve('Some data')
}, 100)
}),
queryKey: ['isFetchingFilter'],
queryFn: () => sleep(10).then(() => 'Some data'),
})
const isFetching = useIsFetching(filter)

Expand All @@ -84,4 +79,23 @@ describe('useIsFetching', () => {

expect(isFetching.value).toStrictEqual(1)
})

test('should work with options getter and be reactive', async () => {
const staleRef = ref(false)
useQuery({
queryKey: ['isFetchingGetter'],
queryFn: () => sleep(10).then(() => 'Some data'),
})
const isFetching = useIsFetching(() => ({
stale: staleRef.value,
queryKey: ['isFetchingGetter'],
}))

expect(isFetching.value).toStrictEqual(0)

staleRef.value = true
await vi.advanceTimersByTimeAsync(0)

expect(isFetching.value).toStrictEqual(1)
})
})
56 changes: 55 additions & 1 deletion packages/vue-query/src/__tests__/useIsMutating.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, test, vi } from 'vitest'
import { onScopeDispose, reactive } from 'vue-demi'
import { onScopeDispose, reactive, ref } from 'vue-demi'
import { sleep } from '@tanstack/query-test-utils'
import { useMutation } from '../useMutation'
import { useIsMutating, useMutationState } from '../useMutationState'
Expand Down Expand Up @@ -88,9 +88,38 @@ describe('useIsMutating', () => {

expect(isMutating.value).toStrictEqual(1)
})

test('should work with options getter and be reactive', async () => {
const keyRef = ref('isMutatingGetter2')
const { mutate } = useMutation({
mutationKey: ['isMutatingGetter'],
mutationFn: (params: string) => sleep(10).then(() => params),
})
mutate('foo')

const isMutating = useIsMutating(() => ({
mutationKey: [keyRef.value],
}))

expect(isMutating.value).toStrictEqual(0)

keyRef.value = 'isMutatingGetter'

await vi.advanceTimersByTimeAsync(0)

expect(isMutating.value).toStrictEqual(1)
})
})

describe('useMutationState', () => {
beforeEach(() => {
vi.useFakeTimers()
})

afterEach(() => {
vi.useRealTimers()
})

it('should return variables after calling mutate 1', () => {
const mutationKey = ['mutation']
const variables = 'foo123'
Expand Down Expand Up @@ -127,4 +156,29 @@ describe('useMutationState', () => {

expect(mutationState.value[0]?.variables).toEqual(variables)
})

it('should work with options getter and be reactive', async () => {
const keyRef = ref('useMutationStateGetter2')
const variables = 'foo123'

const { mutate } = useMutation({
mutationKey: ['useMutationStateGetter'],
mutationFn: (params: string) => sleep(10).then(() => params),
})

mutate(variables)

const mutationState = useMutationState(() => ({
filters: { mutationKey: [keyRef.value], status: 'pending' },
select: (mutation) => mutation.state.variables,
}))

expect(mutationState.value).toEqual([])

keyRef.value = 'useMutationStateGetter'

await vi.advanceTimersByTimeAsync(0)

expect(mutationState.value).toEqual([variables])
})
})
33 changes: 33 additions & 0 deletions packages/vue-query/src/__tests__/useMutation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,39 @@ describe('useMutation', () => {
})
})

test('should work with options getter and be reactive', async () => {
const result = 'Mock data'
const keyRef = ref('key01')
const fnMock = vi.fn((params: string) => sleep(10).then(() => params))
const mutation = useMutation(() => ({
mutationKey: [keyRef.value],
mutationFn: fnMock,
}))

mutation.mutate(result)

await vi.advanceTimersByTimeAsync(10)

expect(fnMock).toHaveBeenCalledTimes(1)
expect(fnMock).toHaveBeenNthCalledWith(
1,
result,
expect.objectContaining({ mutationKey: ['key01'] }),
)

keyRef.value = 'key02'
await vi.advanceTimersByTimeAsync(0)
mutation.mutate(result)
await vi.advanceTimersByTimeAsync(10)

expect(fnMock).toHaveBeenCalledTimes(2)
expect(fnMock).toHaveBeenNthCalledWith(
2,
result,
expect.objectContaining({ mutationKey: ['key02'] }),
)
})

test('should update reactive options', async () => {
const queryClient = useQueryClient()
const mutationCache = queryClient.getMutationCache()
Expand Down
69 changes: 66 additions & 3 deletions packages/vue-query/src/__tests__/useQueries.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ describe('useQueries', () => {
})

test('should be `enabled` to accept getter function', async () => {
const fetchFn = vi.fn()
const fetchFn = vi.fn(() => 'foo')
const checked = ref(false)

useQueries({
Expand All @@ -278,7 +278,7 @@ describe('useQueries', () => {
})

test('should allow getters for query keys', async () => {
const fetchFn = vi.fn()
const fetchFn = vi.fn(() => 'foo')
const key1 = ref('key1')
const key2 = ref('key2')

Expand Down Expand Up @@ -307,7 +307,7 @@ describe('useQueries', () => {
})

test('should allow arbitrarily nested getters for query keys', async () => {
const fetchFn = vi.fn()
const fetchFn = vi.fn(() => 'foo')
const key1 = ref('key1')
const key2 = ref('key2')
const key3 = ref('key3')
Expand Down Expand Up @@ -368,4 +368,67 @@ describe('useQueries', () => {

expect(fetchFn).toHaveBeenCalledTimes(6)
})

test('should work with options getter and be reactive', async () => {
const fetchFn = vi.fn(() => 'foo')
const key1 = ref('key1')
const key2 = ref('key2')
const key3 = ref('key3')
const key4 = ref('key4')
const key5 = ref('key5')

useQueries({
queries: () => [
{
queryKey: [
'key',
key1,
key2.value,
{ key: key3.value },
[{ foo: { bar: key4.value } }],
() => ({
foo: {
bar: {
baz: key5.value,
},
},
}),
],
queryFn: fetchFn,
},
],
})

expect(fetchFn).toHaveBeenCalledTimes(1)

key1.value = 'key1-updated'

await vi.advanceTimersByTimeAsync(0)

expect(fetchFn).toHaveBeenCalledTimes(2)

key2.value = 'key2-updated'

await vi.advanceTimersByTimeAsync(0)

expect(fetchFn).toHaveBeenCalledTimes(3)

key3.value = 'key3-updated'

await vi.advanceTimersByTimeAsync(0)

expect(fetchFn).toHaveBeenCalledTimes(4)

key4.value = 'key4-updated'

await vi.advanceTimersByTimeAsync(0)

expect(fetchFn).toHaveBeenCalledTimes(5)

key5.value = 'key5-updated'

await vi.advanceTimersByTimeAsync(0)

expect(fetchFn).toHaveBeenCalledTimes(6)
})
})
41 changes: 37 additions & 4 deletions packages/vue-query/src/__tests__/useQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,39 @@ describe('useQuery', () => {
})
})

test('should work with options getter and be reactive', async () => {
const keyRef = ref('key011')
const resultRef = ref('result02')
const query = useQuery(() => ({
queryKey: [keyRef.value],
queryFn: () => sleep(0).then(() => resultRef.value),
}))

await vi.advanceTimersByTimeAsync(0)

expect(query).toMatchObject({
status: { value: 'success' },
data: { value: 'result02' },
isPending: { value: false },
isFetching: { value: false },
isFetched: { value: true },
isSuccess: { value: true },
})

resultRef.value = 'result021'
keyRef.value = 'key012'
await vi.advanceTimersByTimeAsync(0)

expect(query).toMatchObject({
status: { value: 'success' },
data: { value: 'result021' },
isPending: { value: false },
isFetching: { value: false },
isFetched: { value: true },
isSuccess: { value: true },
})
})

test('should return pending status initially', () => {
const query = useQuery({
queryKey: ['key1'],
Expand Down Expand Up @@ -274,7 +307,7 @@ describe('useQuery', () => {
})

test('should use the current value for the queryKey when refetch is called', async () => {
const fetchFn = vi.fn()
const fetchFn = vi.fn(() => 'foo')
const keyRef = ref('key11')
const query = useQuery({
queryKey: ['key10', keyRef],
Expand Down Expand Up @@ -302,7 +335,7 @@ describe('useQuery', () => {
})

test('should be `enabled` to accept getter function', async () => {
const fetchFn = vi.fn()
const fetchFn = vi.fn(() => 'foo')
const checked = ref(false)

useQuery({
Expand All @@ -321,7 +354,7 @@ describe('useQuery', () => {
})

test('should allow getters for query keys', async () => {
const fetchFn = vi.fn()
const fetchFn = vi.fn(() => 'foo')
const key1 = ref('key1')
const key2 = ref('key2')

Expand All @@ -346,7 +379,7 @@ describe('useQuery', () => {
})

test('should allow arbitrarily nested getters for query keys', async () => {
const fetchFn = vi.fn()
const fetchFn = vi.fn(() => 'foo')
const key1 = ref('key1')
const key2 = ref('key2')
const key3 = ref('key3')
Expand Down
11 changes: 8 additions & 3 deletions packages/vue-query/src/useIsFetching.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { getCurrentScope, onScopeDispose, ref, watchEffect } from 'vue-demi'
import { useQueryClient } from './useQueryClient'
import { cloneDeepUnref } from './utils'
import type { Ref } from 'vue-demi'
import type { QueryFilters as QF } from '@tanstack/query-core'
import type { MaybeRefDeep } from './types'
import type { QueryClient } from './queryClient'

export type QueryFilters = MaybeRefDeep<QF>
export type QueryFilters = MaybeRefDeep<QF> | (() => MaybeRefDeep<QF>)

export function useIsFetching(
fetchingFilters: MaybeRefDeep<QF> = {},
fetchingFilters: QueryFilters = {},
queryClient?: QueryClient,
): Ref<number> {
if (process.env.NODE_ENV === 'development') {
Expand All @@ -24,7 +25,11 @@ export function useIsFetching(
const isFetching = ref()

const listener = () => {
isFetching.value = client.isFetching(fetchingFilters)
const resolvedFilters =
typeof fetchingFilters === 'function'
? fetchingFilters()
: fetchingFilters
isFetching.value = client.isFetching(cloneDeepUnref(resolvedFilters))
}

const unsubscribe = client.getQueryCache().subscribe(listener)
Expand Down
Loading
Loading