查询
查询基础
查询是对异步数据源的一种声明式依赖,它与一个唯一键相关联。查询可用于任何基于 Promise 的方法(包括 GET 和 POST 方法)来从服务器拉取数据。如果你的方法会修改服务器上的数据,我们建议改用修改。
要在组件中订阅一个查询,请调用 useQuery 函数,并至少传入以下参数:
//: # 'SubscribeDescription'
- 该查询的唯一键
- 一个返回 Promise 的函数,该 Promise:
- 成功解析出数据,或
- 抛出错误
TypeScript
1import { useQuery } from '@tanstack/solid-query'2 3function App() {4 const todosQuery = useQuery(() => ({5 queryKey: ['todos'],6 queryFn: fetchTodoList,7 }))8}你提供的唯一键会在内部用于重新拉取、缓存以及在整个应用中共享该查询。
useQuery 返回的查询结果包含了你在模板渲染及数据其他使用场景中所需的所有查询信息:
TypeScript
1const todosQuery = useQuery(() => ({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 状态,最后默认数据已就绪并渲染成功状态即可:
TypeScript
1import { Switch, Match, For } from 'solid-js'2 3function Todos() {4 const todosQuery = useQuery(() => ({5 queryKey: ['todos'],6 queryFn: fetchTodoList,7 }))8 9 return (10 <Switch>11 <Match when={todosQuery.isPending}>12 <span>Loading...</span>13 </Match>14 <Match when={todosQuery.isError}>15 <span>Error: {todosQuery.error.message}</span>16 </Match>17 <Match when={todosQuery.isSuccess}>18 <ul>19 <For each={todosQuery.data}>{(todo) => <li>{todo.title}</li>}</For>20 </ul>21 </Match>22 </Switch>23 )24}若你不习惯使用布尔值判断,也可直接使用 status 状态:
TypeScript
1import { Switch, Match, For } from 'solid-js'2 3function Todos() {4 const todosQuery = useQuery(() => ({5 queryKey: ['todos'],6 queryFn: fetchTodoList,7 }))8 9 return (10 <Switch>11 <Match when={todosQuery.status === 'pending'}>12 <span>Loading...</span>13 </Match>14 <Match when={todosQuery.status === 'error'}>15 <span>Error: {todosQuery.error.message}</span>16 </Match>17 <Match when={todosQuery.status === 'success'}>18 <ul>19 <For each={todosQuery.data}>{(todo) => <li>{todo.title}</li>}</For>20 </ul>21 </Match>22 </Switch>23 )24}若你在访问 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的情况:拉取操作是否正在运行?