查询
查询基础
查询是对异步数据源的一种声明式依赖,它与一个唯一键相关联。查询可用于任何基于 Promise 的方法(包括 GET 和 POST 方法)来从服务器拉取数据。如果你的方法会修改服务器上的数据,我们建议改用修改。
要在组件或自定义 Hook 中订阅某个查询,请至少传入以下参数调用 useQuery Hook:
- 该查询的唯一键
- 一个返回 Promise 的函数,该 Promise:
- 成功解析出数据,或
- 抛出错误
TypeScript
1import { useQuery } from '@tanstack/vue-query'2 3const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })你提供的唯一键会在内部用于重新拉取、缓存以及在整个应用中共享该查询。
useQuery 返回的查询结果包含了你在模板渲染及其他数据使用场景中所需的所有查询信息:
TypeScript
1const result = useQuery({ queryKey: ['todos'], queryFn: fetchTodoList })result 对象包含几个非常重要的状态,你需要了解这些状态才能高效使用。在任意时刻,查询只能处于以下状态之一:
isPending或status === 'pending'— 查询尚无数据isError或status === 'error'— 查询发生错误isSuccess或status === 'success'— 查询成功,数据已就绪
除上述主要状态外,还可根据查询所处状态获取更多信息:
error— 若查询处于isError状态,则可通过error属性获取错误信息。data— 若查询处于isSuccess状态,则可通过data属性获取数据。isFetching— 在任何状态下,只要查询正在拉取数据(包括后台重新拉取),isFetching均为true。
对于大多数查询,通常只需依次检查 isPending 状态、再检查 isError 状态,最后即可假设数据已就绪并渲染成功状态:
HTML
1<script setup>2import { useQuery } from '@tanstack/vue-query'34const { isPending, isError, data, error } = useQuery({5 queryKey: ['todos'],6 queryFn: fetchTodoList,7})8</script>9 10<template>11 <span v-if="isPending">Loading...</span>12 <span v-else-if="isError">Error: {{ error.message }}</span>13 <!-- We can assume by this point that `isSuccess === true` -->14 <ul v-else-if="data">15 <li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>16 </ul>17</template>若你不习惯使用布尔值,也可始终使用 status 状态:
HTML
1<script setup>2import { useQuery } from '@tanstack/vue-query'34const { status, data, error } = useQuery({5 queryKey: ['todos'],6 queryFn: fetchTodoList,7})8</script>9 10<template>11 <span v-if="status === 'pending'">Loading...</span>12 <span v-else-if="status === 'error'">Error: {{ error.message }}</span>13 <!-- also status === 'success', but "else" logic works, too -->14 <ul v-else-if="data">15 <li v-for="todo in data" :key="todo.id">{{ todo.title }}</li>16 </ul>17</template>若你在访问 data 前已检查过 pending 和 error,TypeScript 还会正确地收窄 data 的类型。
FetchStatus
除 status 字段外,你还会获得一个额外的 fetchStatus 属性,其可取值如下:
fetchStatus === 'fetching'— 查询当前正在拉取数据。fetchStatus === 'paused'— 查询本应拉取数据,但已被暂停。更多细节请参阅网络模式指南。fetchStatus === 'idle'— 查询当前未执行任何操作。
为何需要两种不同状态?
后台重新拉取和“过期时验证”(stale-while-revalidate)逻辑使得 status 和 fetchStatus 的所有组合均可能出现。例如:
- 处于
success状态的查询通常对应idlefetchStatus,但如果此时正进行后台重新拉取,则也可能为fetching。 - 一个刚挂载且尚无数据的查询通常处于
pending状态和fetchingfetchStatus,但如果当前无网络连接,则可能为paused。
因此请注意:查询处于 pending 状态并不代表它正在拉取数据。经验法则是:
status表示关于data的信息:我们是否有数据?fetchStatus表示关于queryFn的信息:它是否正在运行?