概览
@tanstack/solid-query 包提供了一级 API,用于在 SolidJS 中使用 TanStack Query。
例子
TypeScript
1import {2 QueryClient,3 QueryClientProvider,4 createQuery,5} from "@tanstack/solid-query";6import { Switch, Match, For } from "solid-js";7 8const queryClient = new QueryClient();9 10function Example() {11 const query = createQuery(() => ["todos"], fetchTodos);12 13 return (14 <div>15 <Switch>16 <Match when={query.isLoading}>17 <p>Loading...</p>18 </Match>19 <Match when={query.isError}>20 <p>Error: {query.error.message}</p>21 </Match>22 <Match when={query.isSuccess}>23 <For each={query.data}>{(todo) => <p>{todo.title}</p>}</For>24 </Match>25 </Switch>26 </div>27 );28}29 30function App() {31 return (32 <QueryClientProvider client={queryClient}>33 <Example />34 </QueryClientProvider>35 );36}可用的函数
Solid Query 提供了一些有用的原语及函数,使得在 SolidJS 中操作并管理服务器状态变得非常容易。
createQuerycreateQueriescreateInfiniteQueriescreateMutationuseIsFetchinguseIsMutatinguseQueryClientQueryClientQueryClientProvider
Solid Query & React Query 之间的主要差异
Solid Query 提供了一个与 React Query 类似的 API,但有一些关键的区别需要注意。
- 为了保持状态的可响应性,在使用
createQuery、createQueries、createInfiniteQuery及useIsFetching时,查询键值必须包裹在一个函数内:
TypeScript
1// ❌ react version2useQuery(["todos", todo], fetchTodos);3 4// ✅ solid version5createQuery(() => ["todos", todo()], fetchTodos);- 如果你在
<Suspense>组件内访问和查询数据,Suspense 就能开箱即用:
TypeScript
1import { For, Suspense } from "solid-js";2 3function Example() {4 const query = createQuery(() => ["todos"], fetchTodos);5 return (6 <div>7 {/* ✅ 将触发正确的 loading,因为是在 suspense 中访问数据 */}8 <Suspense fallback={"Loading..."}>9 <For each={query.data}>{(todo) => <div>{todo.title}</div>}</For>10 </Suspense>11 {/* ❌ 不会触发 loading,因为是在 suspense 外访问数据. */}12 <For each={query.data}>{(todo) => <div>{todo.title}</div>}</For>13 </div>14 );15}- Solid Query 的原语(如
createX)不支持解构操作。这些函数的返回值是一个 store(译注:不清楚 Solid 中 store 的正式名称),它们的属性在内部被追踪,以支持 SolidJS 的响应式写法:
TypeScript
1import {2 QueryClient,3 QueryClientProvider,4 createQuery,5} from "@tanstack/solid-query";6import { Match, Switch } from "solid-js";7 8const queryClient = new QueryClient();9 10export default function App() {11 return (12 <QueryClientProvider client={queryClient}>13 <Example />14 </QueryClientProvider>15 );16}17 18function Example() {19 // ❌ react version -- 支持解构,因为 react 内部未处理响应式的属性20 // const { isLoading, error, data } = useQuery(['repoData'], () =>21 // fetch('https://api.github.com/repos/tannerlinsley/react-query').then(res =>22 // res.json()23 // )24 // )25 26 // ✅ solid version -- 不支持解构,因为 solid 以此完成响应式编程27 const query = createQuery(28 () => ["repoData"],29 () =>30 fetch("https://api.github.com/repos/tannerlinsley/react-query").then(31 (res) => res.json()32 )33 );34 35 // ✅ 在响应式UI的上下文中访问数据36 return (37 <Switch>38 <Match when={query.isLoading}>Loading...</Match>39 <Match when={query.isError}>Error: {query.error.message}</Match>40 <Match when={query.isSuccess}>41 <div>42 <h1>{query.data.name}</h1>43 <p>{query.data.description}</p>44 <strong>👀 {query.data.subscribers_count}</strong>{" "}45 <strong>✨ {query.data.stargazers_count}</strong>{" "}46 <strong>🍴 {query.data.forks_count}</strong>47 </div>48 </Match>49 </Switch>50 );51}- 如果你希望查询的配置项内容是响应式的,你需要使用对象访问器(getter/setter)的语法来传递它们。可能在一开始会看着比较奇怪,但它确实是更加符合 Solid 习惯的(idiomatic) Solid 代码:
TypeScript
1import {2 QueryClient,3 QueryClientProvider,4 createQuery,5} from "@tanstack/solid-query";6import { createSignal, For } from "solid-js";7 8const queryClient = new QueryClient();9 10function Example() {11 const [enabled, setEnabled] = createSignal(false);12 const query = createQuery(() => ["todos"], fetchTodos, {13 // ❌ 直接单独传递选项不是响应式的14 // enabled: enabled(),15 16 // ✅ 传递一个对象访问器的是响应式的17 get enabled() {18 return enabled();19 },20 });21 22 return (23 <div>24 <Switch>25 <Match when={query.isLoading}>26 <p>Loading...</p>27 </Match>28 <Match when={query.isError}>29 <p>Error: {query.error.message}</p>30 </Match>31 <Match when={query.isSuccess}>32 <For each={query.data}>{(todo) => <p>{todo.title}</p>}</For>33 </Match>34 </Switch>35 <button onClick={() => setEnabled(!enabled())}>Toggle enabled</button>36 </div>37 );38}39 40function App() {41 return (42 <QueryClientProvider client={queryClient}>43 <Example />44 </QueryClientProvider>45 );46}错误可以用 SolidJS 本身的
ErrorBoundary组件来捕获和重置。在 Solid Query 中不需要QueryErrorResetBoundary。由于属性的跟踪是由 Solid 的 fine grained reactivity 处理,因此不需要如
notifyOnChangeProps之类的配置项