360 lines
10 KiB
Markdown
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>
|
|
```
|