查询
查询基础
查询是对异步数据源的一种声明式依赖,它与一个唯一键相关联。查询可用于任何基于 Promise 的方法(包括 GET 和 POST 方法)来从服务器拉取数据。如果你的方法会修改服务器上的数据,我们建议改用修改。
要在组件中订阅一个查询,请调用 createQuery,至少传入以下两项参数:
- 该查询的唯一键
- 一个返回 Promise 的函数,该 Promise:
- 成功解析出数据,或
- 抛出错误
svelte
1<script lang="ts">2 import { createQuery } from '@tanstack/svelte-query'3 const todosQuery = createQuery(() => ({4 queryKey: ['todos'],5 queryFn: fetchTodoList,6 }))7</script>你提供的唯一键会在内部用于重新拉取、缓存以及在整个应用中共享该查询。
createQuery 返回的查询结果对象包含了你在模板渲染及数据其他使用场景中所需的所有查询信息:
TypeScript
1const todosQuery = createQuery(() => ({2 queryKey: ['todos'],3 queryFn: fetchTodoList,4}))result 对象包含若干关键状态,你需要了解这些状态才能高效使用。在任意时刻,查询只能处于以下状态之一:
isPending或status === 'pending'— 查询尚无数据isError或status === 'error'— 查询发生错误isSuccess或status === 'success'— 查询成功,数据已就绪
除上述主要状态外,根据查询所处的具体状态,还可获取更多相关信息:
error— 若查询处于isError状态,则可通过error属性获取错误信息。data— 若查询处于isSuccess状态,则可通过data属性获取数据。isFetching— 在任何状态下,只要查询正在拉取数据(包括后台重新拉取),isFetching均为true。
对于大多数查询,通常只需依次检查 isPending 状态、再检查 isError 状态,最后即可默认数据已就绪并渲染成功状态:
svelte
1<script lang="ts">2 import { createQuery } from '@tanstack/svelte-query'3 4 const todosQuery = createQuery(() => ({5 queryKey: ['todos'],6 queryFn: () => fetchTodos(),7 }))8</script>9 10<div>11 {#if todosQuery.isPending}12 <p>Loading...</p>13 {:else if todosQuery.isError}14 <p>Error: {todosQuery.error.message}</p>15 {:else if todosQuery.isSuccess}16 {#each todosQuery.data as todo}17 <p>{todo.title}</p>18 {/each}19 {/if}20</div>如果你不习惯使用布尔值,也可以直接使用 status 状态:
svelte
1<script lang="ts">2 const todosQuery = createQuery(() => ({3 queryKey: ['todos'],4 queryFn: () => fetchTodos(),5 }))6</script>7 8<div>9 {#if todosQuery.status === 'pending'}10 <p>Loading...</p>11 {:else if todosQuery.status === 'error'}12 <p>Error: {todosQuery.error.message}</p>13 {:else if todosQuery.status === 'success'}14 {#each todosQuery.data as todo}15 <p>{todo.title}</p>16 {/each}17 {/if}18</div>若你在访问 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的信息:它是否正在运行?