function useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryDefinedReturnType<TData, TError>;Defined in: packages/vue-query/src/useQuery.ts:65
This overload is selected when initialData is set, so the resulting data is never undefined.
enabled tracks reactive dependencies automatically as a ref, a plain value, or a reactive getter (() => ...). queryKey reacts through a ref or a reactive getter for the array itself, or refs and reactive getters as individual entries. Other options are read once when passed as a plain value, and stay reactive when passed as a ref or a computed.
TQueryFnData = unknown
TError = Error
TData = TQueryFnData
TQueryKey extends readonly unknown[] = readonly unknown[]
DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>
The DefinedInitialQueryOptions to use — everything you can pass to useQuery, with initialData set.
Use this to use a custom QueryClient. Otherwise, the one provided by VueQueryPlugin will be used.
UseQueryDefinedReturnType<TData, TError>
The current query result, typed so that data is never undefined (status never resolves to pending in this overload's type, since initialData guarantees data upfront).
<script setup lang="ts">
import { useQuery } from '@tanstack/vue-query'
// `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails,
// so the list stays visible alongside the error.
const { data, isError, error } = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
initialData: [],
})
</script>
<template>
<span v-if="isError">Error: {{ error.message }}</span>
<ul>
<li v-for="post in data" :key="post.id">{{ post.title }}</li>
</ul>
</template>function useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryReturnType<TData, TError>;Defined in: packages/vue-query/src/useQuery.ts:206
enabled tracks reactive dependencies automatically as a ref, a plain value, or a reactive getter (() => ...). queryKey reacts through a ref or a reactive getter for the array itself, or refs and reactive getters as individual entries. Other options are read once when passed as a plain value, and stay reactive when passed as a ref or a computed.
TQueryFnData = unknown
TError = Error
TData = TQueryFnData
TQueryKey extends readonly unknown[] = readonly unknown[]
UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>
The UndefinedInitialQueryOptions to use — everything you can pass to useQuery.
Use this to use a custom QueryClient. Otherwise, the one provided by VueQueryPlugin will be used.
UseQueryReturnType<TData, TError>
The current query result. status is pending if there is no cached data to display, error if the last fetch attempt failed, or success if the query has data to display.
A query key built from a reactive ref — the query refetches whenever postId changes:
<script setup lang="ts">
import { ref } from 'vue'
import { useQuery } from '@tanstack/vue-query'
const postId = ref(1)
const { status, data, error } = useQuery({
queryKey: ['post', postId],
queryFn: () => fetchPost(postId.value),
})
</script>
<template>
<span v-if="status === 'pending'">Loading...</span>
<span v-else-if="status === 'error'">Error: {{ error.message }}</span>
<h1 v-else>{{ data.title }}</h1>
</template>select derives whatever data a component needs from the cached value, without changing what's actually stored in the cache — the cache still holds the full Post[], but data here is a number:
<script setup lang="ts">
import { useQuery } from '@tanstack/vue-query'
const { data, isPending, isError, error } = useQuery({
queryKey: ['posts'],
queryFn: fetchPosts,
select: (posts) => posts.length,
})
</script>
<template>
<span v-if="isPending">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<span v-else>{{ data }} posts</span>
</template>A dependent query, only enabled once postId is set — use isLoading, not isPending, so the loading state doesn't show while the query is disabled:
<script setup lang="ts">
import { ref } from 'vue'
import { useQuery } from '@tanstack/vue-query'
const props = defineProps<{ postId: number | undefined }>()
const { data, isLoading, isError, error } = useQuery({
queryKey: ['post', props.postId],
queryFn: () => fetchPost(props.postId!),
enabled: () => props.postId != null,
})
</script>
<template>
<span v-if="props.postId == null">Select a post</span>
<span v-else-if="isLoading">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<h1 v-else>{{ data?.title }}</h1>
</template>Seeding a detail query from an already-cached list, to skip the loading state:
<script setup lang="ts">
import { useQuery, useQueryClient } from '@tanstack/vue-query'
const props = defineProps<{ postId: number }>()
const queryClient = useQueryClient()
const { data, isError, error } = useQuery({
queryKey: ['post', props.postId],
queryFn: () => fetchPost(props.postId),
initialData: () =>
queryClient
.getQueryData<Array<Post>>(['posts'])
?.find((post) => post.id === props.postId),
})
</script>
<template>
<span v-if="isError">Error: {{ error.message }}</span>
<h1 v-else>{{ data?.title }}</h1>
</template>Paginated data, keeping the previous page's data visible while the next page loads:
<script setup lang="ts">
import { ref } from 'vue'
import { keepPreviousData, useQuery } from '@tanstack/vue-query'
const page = ref(0)
const { data, isPlaceholderData, isError, error } = useQuery({
queryKey: ['posts', page],
queryFn: () => fetchPosts(page.value),
placeholderData: keepPreviousData,
})
</script>
<template>
<span v-if="isError">Error: {{ error.message }}</span>
<template v-else>
<ul>
<li v-for="post in data" :key="post.id">{{ post.title }}</li>
</ul>
<button :disabled="isPlaceholderData" @click="page++">Next Page</button>
</template>
</template>function useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryReturnType<TData, TError>;Defined in: packages/vue-query/src/useQuery.ts:282
Fallback overload for options whose initialData presence isn't statically known — for example, a ref/reactive object built up conditionally, rather than a plain object literal. Prefer one of the other overloads when possible, since they infer whether data can be undefined from initialData directly.
enabled tracks reactive dependencies automatically as a ref, a plain value, or a reactive getter (() => ...). queryKey reacts through a ref or a reactive getter for the array itself, or refs and reactive getters as individual entries.
When options itself is a reactive getter, the whole object is re-evaluated on every change to its dependencies, so any option inside it — not just queryKey and enabled — can change over time.
TQueryFnData = unknown
TError = Error
TData = TQueryFnData
TQueryKey extends readonly unknown[] = readonly unknown[]
MaybeRefOrGetter<UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>>
A ref, plain value, or reactive getter resolving to the UseQueryOptions to use.
Use this to use a custom QueryClient. Otherwise, the one provided by VueQueryPlugin will be used.
UseQueryReturnType<TData, TError>
The current query result, with data typed as possibly undefined.
Passing a whole-options getter so staleTime reacts to a setting stored elsewhere, not just queryKey:
<script setup lang="ts">
import { useQuery } from '@tanstack/vue-query'
const props = defineProps<{ id: number; staleTime: number }>()
const { data } = useQuery(() => ({
queryKey: ['post', props.id],
queryFn: () => fetchPost(props.id),
staleTime: props.staleTime,
}))
</script>
<template>
<h1 v-if="data">{{ data.title }}</h1>
</template>skipToken disables the query in a type-safe way, without a non-null assertion on props.postId — queryFn is only ever called when it's defined. The whole-options getter re-evaluates queryFn on every change to props.postId. queryFn can also be a computed, but never a bare getter, since a function there is the query function itself. refetch doesn't work while queryFn is skipToken — use enabled: false instead if you need to trigger the query manually:
<script setup lang="ts">
import { skipToken, useQuery } from '@tanstack/vue-query'
const props = defineProps<{ postId: number | undefined }>()
const { data, isLoading, isError, error } = useQuery(() => {
const postId = props.postId
return {
queryKey: ['post', postId],
queryFn: postId != null ? () => fetchPost(postId) : skipToken,
}
})
</script>
<template>
<span v-if="props.postId == null">Select a post</span>
<span v-else-if="isLoading">Loading...</span>
<span v-else-if="isError">Error: {{ error.message }}</span>
<h1 v-else>{{ data?.title }}</h1>
</template>