useQuery
概述
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。
调用签名
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。否则,将使用由 VueQueryPlugin 提供的 QueryClient。
返回值
UseQueryDefinedReturnType<TData, TError>
当前查询结果,其类型确保 data 永远不会是 undefined(除非某个 select 将 TData 更改为包含 undefined)。在此重载的类型定义中,status 永远不会解析为 pending,因为 initialData 保证了数据的即时可用性。
示例
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>调用签名
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。否则,将使用由 VueQueryPlugin 提供的 QueryClient。
返回值
UseQueryReturnType<TData, TError>
当前查询结果。若无缓存数据可供显示,则 status 为 pending;若上一次拉取尝试失败,则为 error;若查询已有数据可供显示,则为 success。
示例
由响应式 ref 构建的查询键 —— 当 postId 变化时,查询将重新拉取:
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:
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,以避免查询禁用期间显示加载状态:
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,其计时起点是列表被拉取的时间,而非当前时间:
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>分页数据,在加载下一页时保持上一页数据可见:
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>调用签名
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。否则,将使用由 VueQueryPlugin 提供的 QueryClient。
返回值
UseQueryReturnType<TData, TError>
当前查询结果,其中 data 的类型被声明为可能为 undefined。
示例
传入整个选项的 getter,使 staleTime 响应于其他位置存储的设置,而不仅限于 queryKey:
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:
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。否则,将使用由 VueQueryPlugin 提供的 QueryClient。
返回值
UseQueryReturnType<TData, TError>
当前查询结果,其中 data 的类型被声明为可能为 undefined。