T
TanStack2y ago
deep-jade

QueryOptions return type

I want to create a Link component that handles routing but also want to prefetch data if the user hovers that link. I already make use of the queryOptions api so i created this factory
export const clientQueries = {
all: () => ['clients'],
// These are the initial values when user navigates to the clients page, so we can prefetch these fields
getInitial: () =>
queryOptions({
queryKey: [...clientQueries.all(), 'get', { per_page: 10, page: 1 }],
queryFn: () => clientService.get({ queries: { per_page: 10, page: 1 } }),
placeholderData: keepPreviousData,
}),
get: (filters: Ref<ClientsRequest>) =>
queryOptions({
queryKey: [...clientQueries.all(), 'get', {filters}],
queryFn: () => clientService.get({ queries: { ...filters.value } }),
placeholderData: keepPreviousData,
})
}
export const clientQueries = {
all: () => ['clients'],
// These are the initial values when user navigates to the clients page, so we can prefetch these fields
getInitial: () =>
queryOptions({
queryKey: [...clientQueries.all(), 'get', { per_page: 10, page: 1 }],
queryFn: () => clientService.get({ queries: { per_page: 10, page: 1 } }),
placeholderData: keepPreviousData,
}),
get: (filters: Ref<ClientsRequest>) =>
queryOptions({
queryKey: [...clientQueries.all(), 'get', {filters}],
queryFn: () => clientService.get({ queries: { ...filters.value } }),
placeholderData: keepPreviousData,
})
}
I want to make a component like this
<template>
<RouterLink
:to
class="text-sm font-medium transition-colors hover:text-primary"
@hover="prefetch"
>
<slot></slot>
</RouterLink>
</template>

<script lang="ts" setup>
import { useQueryClient, type QueryOptions } from '@tanstack/vue-query';
import type { RouteLocationRaw } from 'vue-router';

const props = defineProps<{
to: RouteLocationRaw,
prefetch?: QueryOptions
}>()

const queryClient = useQueryClient()
const prefetch = () => {
console.log('hover')
if (!props.prefetch) return
queryClient.prefetchQuery(props.prefetch)
}
</script>
<template>
<RouterLink
:to
class="text-sm font-medium transition-colors hover:text-primary"
@hover="prefetch"
>
<slot></slot>
</RouterLink>
</template>

<script lang="ts" setup>
import { useQueryClient, type QueryOptions } from '@tanstack/vue-query';
import type { RouteLocationRaw } from 'vue-router';

const props = defineProps<{
to: RouteLocationRaw,
prefetch?: QueryOptions
}>()

const queryClient = useQueryClient()
const prefetch = () => {
console.log('hover')
if (!props.prefetch) return
queryClient.prefetchQuery(props.prefetch)
}
</script>
so you could use it like:
<script setup lang="ts">
import Link from '@/components/navigation/Link.vue';
import { clientQueries } from '@/queries/clients';
</script>

<template>
<Link
to="/examples/dashboard"
:prefetch="clientQueries.getInitial()"
class="text-sm font-medium text-muted-foreground transition-colors hover:text-primary"
>
Customers
</Link>
</template>
<script setup lang="ts">
import Link from '@/components/navigation/Link.vue';
import { clientQueries } from '@/queries/clients';
</script>

<template>
<Link
to="/examples/dashboard"
:prefetch="clientQueries.getInitial()"
class="text-sm font-medium text-muted-foreground transition-colors hover:text-primary"
>
Customers
</Link>
</template>
However, i cant get to type to work correctly for the prefetch prop.
4 Replies
deep-jade
deep-jadeOP2y ago
For now it seems UseQueriesOptions<any> would be working.
rival-black
rival-black2y ago
I think you need to type the props as
prefetch?: ReturnType<typeof clientQueries["getInitial" | "get"]>
prefetch?: ReturnType<typeof clientQueries["getInitial" | "get"]>
Then you can only pass in whatever the return type of get and getInitial are
deep-jade
deep-jadeOP2y ago
Thanks for your answer but I will be creating a lot more query options so adding them all there not really be helpful.
rival-black
rival-black2y ago
prefetch?: ReturnType<typeof clientQueries[Exclude<keyof typeof clientQueries, "all">]>
prefetch?: ReturnType<typeof clientQueries[Exclude<keyof typeof clientQueries, "all">]>
Then it might be easier for you to do an Exclude on clientQueries to remove all the ones you don't want

Did you find this page helpful?