译零 TransZero · TanStack Query 中文文档
主站

useQuery

更新于 2026-11-02 Vue 查看英文原文 ↗

概述

TypeScript
1function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends readonly unknown[] = readonly unknown[]>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryDefinedReturnType<TData, TError>;2function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends readonly unknown[] = readonly unknown[]>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;3function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends readonly unknown[] = readonly unknown[]>(options: MaybeRefOrGetter<UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;
  • DefinedInitialQueryOptions → UseQueryDefinedReturnType:当 initialData 已知被定义时,选择此重载,因此返回的 data 永远不会是 undefined(除非某个 select 将 TData 更改为包含 undefined)。
  • UndefinedInitialQueryOptions → UseQueryReturnType:enabled 会自动追踪响应式依赖,其形式可以是 ref、普通值或响应式 getter(() => ...)。queryKey 通过 ref 或数组本身的响应式 getter 进行响应,也可将 ref 和响应式 getter 作为独立条目进行响应。其他选项若以普通值形式传入,则仅读取一次;若以 ref 或 computed 形式传入,则保持响应式。
  • MaybeRefOrGetter → UseQueryReturnType:当选项中 initialData 的存在性在静态类型层面无法确定时(例如,条件式构建的 ref/响应式对象,而非普通对象字面量),使用此后备重载。尽可能优先选用其他重载,因为它们能直接根据 initialData 推断 data 是否可能为 undefined。

另请参阅:参数 · 返回值

调用签名

TypeScript
1function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends readonly unknown[] = readonly unknown[]>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryDefinedReturnType<TData, TError>;

定义于:packages/vue-query/src/useQuery.ts:74

当 initialData 已知被定义时,选择此重载,因此返回的 data 永远不会是 undefined(除非某个 select 将 TData 更改为包含 undefined)。

enabled 会自动追踪响应式依赖,其形式可以是 ref、普通值或响应式 getter(() => ...)。queryKey 通过 ref 或数组本身的响应式 getter 进行响应,也可将 ref 和响应式 getter 作为独立条目进行响应。其他选项若以普通值形式传入,则仅读取一次;若以 ref 或 computed 形式传入,则保持响应式。

类型参数

TQueryFnData

TQueryFnData = unknown

TError

TError = Error

TData

TData = TQueryFnData

TQueryKey

TQueryKey extends readonly unknown[] = readonly unknown[]

参数

options

DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>

要使用的 DefinedInitialQueryOptions —— 即所有可传给 useQuery 的选项,且 initialData 已知被定义。

queryClient?

QueryClient

使用此参数可指定自定义的 QueryClient。否则,将使用由 VueQueryPlugin 提供的 QueryClient。

返回值

UseQueryDefinedReturnType<TData, TError>

当前查询结果,其类型确保 data 永远不会是 undefined(除非某个 select 将 TData 更改为包含 undefined)。在此重载的类型定义中,status 永远不会解析为 pending,因为 initialData 保证了数据的即时可用性。

示例

HTML
1<script setup lang="ts">2import { useQuery } from '@tanstack/vue-query'34// `data` is `Post[]`, never `undefined`, thanks to `initialData` — even if a refetch fails,5// so the list stays visible alongside the error.6const { data, isError, error } = useQuery({7  queryKey: ['posts'],8  queryFn: fetchPosts,9  initialData: [],10})11</script>12 13<template>14  <span v-if="isError">Error: {{ error.message }}</span>15  <ul>16    <li v-for="post in data" :key="post.id">{{ post.title }}</li>17  </ul>18</template>

调用签名

TypeScript
1function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends readonly unknown[] = readonly unknown[]>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;

定义于:packages/vue-query/src/useQuery.ts:213

enabled 会自动追踪响应式依赖,其形式可以是 ref、普通值或响应式 getter(() => ...)。queryKey 通过 ref 或数组本身的响应式 getter 进行响应,也可将 ref 和响应式 getter 作为独立条目进行响应。其他选项若以普通值形式传入,则仅读取一次;若以 ref 或 computed 形式传入,则保持响应式。

类型参数

TQueryFnData

TQueryFnData = unknown

TError

TError = Error

TData

TData = TQueryFnData

TQueryKey

TQueryKey extends readonly unknown[] = readonly unknown[]

参数

options

UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>

要使用的 UndefinedInitialQueryOptions —— 即所有可传给 useQuery 的选项。

queryClient?

QueryClient

使用此参数可指定自定义的 QueryClient。否则,将使用由 VueQueryPlugin 提供的 QueryClient。

返回值

UseQueryReturnType<TData, TError>

当前查询结果。若无缓存数据可供显示,则 status 为 pending;若上一次拉取尝试失败,则为 error;若查询已有数据可供显示,则为 success。

示例

由响应式 ref 构建的查询键 —— 当 postId 变化时,查询将重新拉取:

HTML
1<script setup lang="ts">2import { ref } from 'vue'3import { useQuery } from '@tanstack/vue-query'45const postId = ref(1)6const { status, data, error } = useQuery({7  queryKey: ['post', postId],8  queryFn: () => fetchPost(postId.value),9})10</script>11 12<template>13  <span v-if="status === 'pending'">Loading...</span>14  <span v-else-if="status === 'error'">Error: {{ error.message }}</span>15  <h1 v-else>{{ data.title }}</h1>16</template>

select 从缓存值中派生组件所需的 data,而不会改变缓存中实际存储的内容 —— 缓存仍保存完整的 Post[],但此处的 data 是一个 number:

HTML
1<script setup lang="ts">2import { useQuery } from '@tanstack/vue-query'34const { data, isPending, isError, error } = useQuery({5  queryKey: ['posts'],6  queryFn: fetchPosts,7  select: (posts) => posts.length,8})9</script>10 11<template>12  <span v-if="isPending">Loading...</span>13  <span v-else-if="isError">Error: {{ error.message }}</span>14  <span v-else>{{ data }} posts</span>15</template>

依赖型查询,仅当 postId 被设置后才启用 —— 使用 isLoading,而非 isPending,以避免查询禁用期间显示加载状态:

HTML
1<script setup lang="ts">2import { ref } from 'vue'3import { useQuery } from '@tanstack/vue-query'45const props = defineProps<{ postId: number | undefined }>()67const { data, isLoading, isError, error } = useQuery({8  queryKey: ['post', props.postId],9  queryFn: () => fetchPost(props.postId!),10  enabled: () => props.postId != null,11})12</script>13 14<template>15  <span v-if="props.postId == null">Select a post</span>16  <span v-else-if="isLoading">Loading...</span>17  <span v-else-if="isError">Error: {{ error.message }}</span>18  <h1 v-else>{{ data?.title }}</h1>19</template>

利用已缓存的列表预填充详情查询,从而跳过加载状态。initialDataUpdatedAt 继承列表自身的拉取时间,因此若你设置了 staleTime,其计时起点是列表被拉取的时间,而非当前时间:

HTML
1<script setup lang="ts">2import { useQuery, useQueryClient } from '@tanstack/vue-query'34const props = defineProps<{ postId: number }>()5const queryClient = useQueryClient()67const { data, isError, error } = useQuery({8  queryKey: ['post', props.postId],9  queryFn: () => fetchPost(props.postId),10  initialData: () =>11    queryClient12      .getQueryData<Array<Post>>(['posts'])13      ?.find((post) => post.id === props.postId),14  initialDataUpdatedAt: () =>15    queryClient.getQueryState(['posts'])?.dataUpdatedAt,16})17</script>18 19<template>20  <span v-if="isError">Error: {{ error.message }}</span>21  <h1 v-else>{{ data?.title }}</h1>22</template>

分页数据,在加载下一页时保持上一页数据可见:

HTML
1<script setup lang="ts">2import { ref } from 'vue'3import { keepPreviousData, useQuery } from '@tanstack/vue-query'45const page = ref(0)67const { data, isPlaceholderData, isError, error } = useQuery({8  queryKey: ['posts', page],9  queryFn: () => fetchPosts(page.value),10  placeholderData: keepPreviousData,11})12</script>13 14<template>15  <span v-if="isError">Error: {{ error.message }}</span>16  <template v-else>17    <ul>18      <li v-for="post in data" :key="post.id">{{ post.title }}</li>19    </ul>20    <button :disabled="isPlaceholderData" @click="page++">Next Page</button>21  </template>22</template>

调用签名

TypeScript
1function useQuery<TQueryFnData = unknown, TError = Error, TData = TQueryFnData, TQueryKey extends readonly unknown[] = readonly unknown[]>(options: MaybeRefOrGetter<UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;

定义于:packages/vue-query/src/useQuery.ts:286

当选项中 initialData 的存在性在静态类型层面无法确定时(例如,条件式构建的 ref/响应式对象,而非普通对象字面量),使用此后备重载。尽可能优先选用其他重载,因为它们能直接根据 initialData 推断 data 是否可能为 undefined。

enabled 会自动追踪响应式依赖,其形式可以是 ref、普通值或响应式 getter(() => ...)。queryKey 通过 ref 或数组本身的响应式 getter 进行响应,也可将 ref 和响应式 getter 作为独立条目进行响应。

当 options 本身是一个响应式 getter 时,整个对象会在其依赖项每次变更时重新求值,因此其中任意选项(不仅限于 queryKey 和 enabled)都可能随时间变化。

类型参数

TQueryFnData

TQueryFnData = unknown

TError

TError = Error

TData

TData = TQueryFnData

TQueryKey

TQueryKey extends readonly unknown[] = readonly unknown[]

参数

options

MaybeRefOrGetter<UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>>

一个 ref、普通值或响应式 getter,其解析结果为要使用的 UseQueryOptions。

queryClient?

QueryClient

使用此参数可指定自定义的 QueryClient。否则,将使用由 VueQueryPlugin 提供的 QueryClient。

返回值

UseQueryReturnType<TData, TError>

当前查询结果,其中 data 的类型被声明为可能为 undefined。

示例

传入整个选项的 getter,使 staleTime 响应于其他位置存储的设置,而不仅限于 queryKey:

HTML
1<script setup lang="ts">2import { useQuery } from '@tanstack/vue-query'34const props = defineProps<{ id: number; staleTime: number }>()56const { data } = useQuery(() => ({7  queryKey: ['post', props.id],8  queryFn: () => fetchPost(props.id),9  staleTime: props.staleTime,10}))11</script>12 13<template>14  <h1 v-if="data">{{ data.title }}</h1>15</template>

skipToken 以类型安全的方式禁用查询,无需对 props.postId 进行非空断言 —— queryFn 仅在有定义时才会被调用。整个选项的 getter 会在 props.postId 每次变更时重新求值 queryFn。queryFn 也可以是 computed,但绝不能是裸函数(bare getter),因为该位置的函数即为查询函数本身。当 queryFn 为 skipToken 时,refetch 不起作用 —— 若需手动触发查询,请改用 enabled: false:

HTML
1<script setup lang="ts">2import { skipToken, useQuery } from '@tanstack/vue-query'34const props = defineProps<{ postId: number | undefined }>()56const { data, isLoading, isError, error } = useQuery(() => {7  const postId = props.postId8  return {9    queryKey: ['post', postId],10    queryFn: postId != null ? () => fetchPost(postId) : skipToken,11  }12})13</script>14 15<template>16  <span v-if="props.postId == null">Select a post</span>17  <span v-else-if="isLoading">Loading...</span>18  <span v-else-if="isError">Error: {{ error.message }}</span>19  <h1 v-else>{{ data?.title }}</h1>20</template>

参数

options

MaybeRefOrGetter<UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>>

一个 ref、普通值或响应式 getter,其解析结果为要使用的 UseQueryOptions。

queryClient?

QueryClient

使用此参数可指定自定义的 QueryClient。否则,将使用由 VueQueryPlugin 提供的 QueryClient。

返回值

UseQueryReturnType<TData, TError>

当前查询结果,其中 data 的类型被声明为可能为 undefined。

本页为 TanStack Query 文档(Vue 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de