Files
upstream-mirror 3a013ccdfe
Some checks failed
autofix.ci / autofix (push) Failing after 4s
Release / Release (push) Has been skipped
GitHub Actions Security Analysis / Run zizmor (push) Failing after 2s
snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:13:08 +05:00

360 lines
10 KiB
Markdown

---
id: useQuery
title: useQuery
---
## Call Signature
```ts
function useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryDefinedReturnType<TData, TError>;
```
Defined in: [packages/vue-query/src/useQuery.ts:65](https://github.com/TanStack/query/blob/main/packages/vue-query/src/useQuery.ts#L65)
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 `ref`s 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`.
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### options
[`DefinedInitialQueryOptions`](../type-aliases/DefinedInitialQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
The [DefinedInitialQueryOptions](../type-aliases/DefinedInitialQueryOptions.md) to use — everything you can pass to `useQuery`, with
`initialData` set.
#### queryClient?
[`QueryClient`](../classes/QueryClient.md)
Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin`
will be used.
### Returns
[`UseQueryDefinedReturnType`](../type-aliases/UseQueryDefinedReturnType.md)\<`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).
### Example
```vue
<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>
```
## Call Signature
```ts
function useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryReturnType<TData, TError>;
```
Defined in: [packages/vue-query/src/useQuery.ts:206](https://github.com/TanStack/query/blob/main/packages/vue-query/src/useQuery.ts#L206)
`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 `ref`s 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`.
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### options
[`UndefinedInitialQueryOptions`](../type-aliases/UndefinedInitialQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryKey`\>
The [UndefinedInitialQueryOptions](../type-aliases/UndefinedInitialQueryOptions.md) to use — everything you can pass to `useQuery`.
#### queryClient?
[`QueryClient`](../classes/QueryClient.md)
Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin`
will be used.
### Returns
[`UseQueryReturnType`](../type-aliases/UseQueryReturnType.md)\<`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.
### Examples
A query key built from a reactive `ref` — the query refetches whenever `postId` changes:
```vue
<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`:
```vue
<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:
```vue
<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:
```vue
<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:
```vue
<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>
```
## Call Signature
```ts
function useQuery<TQueryFnData, TError, TData, TQueryKey>(options, queryClient?): UseQueryReturnType<TData, TError>;
```
Defined in: [packages/vue-query/src/useQuery.ts:282](https://github.com/TanStack/query/blob/main/packages/vue-query/src/useQuery.ts#L282)
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 `ref`s 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.
### Type Parameters
#### TQueryFnData
`TQueryFnData` = `unknown`
#### TError
`TError` = `Error`
#### TData
`TData` = `TQueryFnData`
#### TQueryKey
`TQueryKey` *extends* readonly `unknown`[] = readonly `unknown`[]
### Parameters
#### options
`MaybeRefOrGetter`\<[`UseQueryOptions`](../type-aliases/UseQueryOptions.md)\<`TQueryFnData`, `TError`, `TData`, `TQueryFnData`, `TQueryKey`\>\>
A `ref`, plain value, or reactive getter resolving to the [UseQueryOptions](../type-aliases/UseQueryOptions.md) to use.
#### queryClient?
[`QueryClient`](../classes/QueryClient.md)
Use this to use a custom `QueryClient`. Otherwise, the one provided by `VueQueryPlugin`
will be used.
### Returns
[`UseQueryReturnType`](../type-aliases/UseQueryReturnType.md)\<`TData`, `TError`\>
The current query result, with `data` typed as possibly `undefined`.
### Examples
Passing a whole-options getter so `staleTime` reacts to a setting stored elsewhere, not just `queryKey`:
```vue
<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:
```vue
<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>
```