框架
版本

useQuery

tsx
const {
  data,
  dataUpdatedAt,
  error,
  errorUpdatedAt,
  failureCount,
  failureReason,
  fetchStatus,
  isError,
  isFetched,
  isFetchedAfterMount,
  isFetching,
  isInitialLoading,
  isLoading,
  isLoadingError,
  isPaused,
  isPending,
  isPlaceholderData,
  isRefetchError,
  isRefetching,
  isStale,
  isSuccess,
  refetch,
  status,
} = useQuery(
  () => ({
    queryKey,
    queryFn,
    enabled,
    select,
    placeholderData,
    deferStream,
    reconcile,
    gcTime,
    networkMode,
    initialData,
    initialDataUpdatedAt,
    meta,
    queryKeyHashFn,
    refetchInterval,
    refetchIntervalInBackground,
    refetchOnMount,
    refetchOnReconnect,
    refetchOnWindowFocus,
    retry,
    retryOnMount,
    retryDelay,
    staleTime,
    throwOnError,
  }),
  () => queryClient,
)
const {
  data,
  dataUpdatedAt,
  error,
  errorUpdatedAt,
  failureCount,
  failureReason,
  fetchStatus,
  isError,
  isFetched,
  isFetchedAfterMount,
  isFetching,
  isInitialLoading,
  isLoading,
  isLoadingError,
  isPaused,
  isPending,
  isPlaceholderData,
  isRefetchError,
  isRefetching,
  isStale,
  isSuccess,
  refetch,
  status,
} = useQuery(
  () => ({
    queryKey,
    queryFn,
    enabled,
    select,
    placeholderData,
    deferStream,
    reconcile,
    gcTime,
    networkMode,
    initialData,
    initialDataUpdatedAt,
    meta,
    queryKeyHashFn,
    refetchInterval,
    refetchIntervalInBackground,
    refetchOnMount,
    refetchOnReconnect,
    refetchOnWindowFocus,
    retry,
    retryOnMount,
    retryDelay,
    staleTime,
    throwOnError,
  }),
  () => queryClient,
)

用法示例

以下是一些如何在 Solid Query 中使用 useQuery 原语的示例。

基本用法

useQuery 最基本的用法是创建一个从 API 获取数据的查询。

tsx
import { useQuery } from '@tanstack/solid-query'

function App() {
  const todos = useQuery(() => ({
    queryKey: 'todos',
    queryFn: async () => {
      const response = await fetch('/api/todos')
      if (!response.ok) {
        throw new Error('获取待办事项失败')
      }
      return response.json()
    },
  }))

  return (
    <div>
      <Show when={todos.isError}>
        <div>错误:{todos.error.message}</div>
      </Show>
      <Show when={todos.isLoading}>
        <div>加载中...</div>
      </Show>
      <Show when={todos.isSuccess}>
        <div>
          <div>待办事项:</div>
          <ul>
            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
          </ul>
        </div>
      </Show>
    </div>
  )
}
import { useQuery } from '@tanstack/solid-query'

function App() {
  const todos = useQuery(() => ({
    queryKey: 'todos',
    queryFn: async () => {
      const response = await fetch('/api/todos')
      if (!response.ok) {
        throw new Error('获取待办事项失败')
      }
      return response.json()
    },
  }))

  return (
    <div>
      <Show when={todos.isError}>
        <div>错误:{todos.error.message}</div>
      </Show>
      <Show when={todos.isLoading}>
        <div>加载中...</div>
      </Show>
      <Show when={todos.isSuccess}>
        <div>
          <div>待办事项:</div>
          <ul>
            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
          </ul>
        </div>
      </Show>
    </div>
  )
}

响应式选项

useQuery 接受一个返回对象的函数的原因是允许响应式选项。当查询选项依赖于其他可能随时间变化的值/信号时,这很有用。Solid Query 可以在响应式作用域中跟踪传递的函数,并在依赖项更改时重新运行它。

tsx
import { useQuery } from '@tanstack/solid-query'

function App() {
  const [filter, setFilter] = createSignal('all')

  const todos = useQuery(() => ({
    queryKey: ['todos', filter()],
    queryFn: async () => {
      const response = await fetch(`/api/todos?filter=${filter()}`)
      if (!response.ok) {
        throw new Error('获取待办事项失败')
      }
      return response.json()
    },
  }))

  return (
    <div>
      <div>
        <button onClick={() => setFilter('all')}>全部</button>
        <button onClick={() => setFilter('active')}>活动</button>
        <button onClick={() => setFilter('completed')}>已完成</button>
      </div>
      <Show when={todos.isError}>
        <div>错误:{todos.error.message}</div>
      </Show>
      <Show when={todos.isLoading}>
        <div>加载中...</div>
      </Show>
      <Show when={todos.isSuccess}>
        <div>
          <div>待办事项:</div>
          <ul>
            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
          </ul>
        </div>
      </Show>
    </div>
  )
}
import { useQuery } from '@tanstack/solid-query'

function App() {
  const [filter, setFilter] = createSignal('all')

  const todos = useQuery(() => ({
    queryKey: ['todos', filter()],
    queryFn: async () => {
      const response = await fetch(`/api/todos?filter=${filter()}`)
      if (!response.ok) {
        throw new Error('获取待办事项失败')
      }
      return response.json()
    },
  }))

  return (
    <div>
      <div>
        <button onClick={() => setFilter('all')}>全部</button>
        <button onClick={() => setFilter('active')}>活动</button>
        <button onClick={() => setFilter('completed')}>已完成</button>
      </div>
      <Show when={todos.isError}>
        <div>错误:{todos.error.message}</div>
      </Show>
      <Show when={todos.isLoading}>
        <div>加载中...</div>
      </Show>
      <Show when={todos.isSuccess}>
        <div>
          <div>待办事项:</div>
          <ul>
            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
          </ul>
        </div>
      </Show>
    </div>
  )
}

Suspense 一起使用

当查询处于挂起或错误状态时,useQuery 支持触发 SolidJS SuspenseErrorBoundary 组件。这使您可以轻松地处理组件中的加载和错误状态。

tsx
import { useQuery } from '@tanstack/solid-query'

function App() {
  const todos = useQuery(() => ({
    queryKey: 'todos',
    queryFn: async () => {
      const response = await fetch('/api/todos')
      if (!response.ok) {
        throw new Error('获取待办事项失败')
      }
      return response.json()
    },
    throwOnError: true,
  }))

  return (
    <ErrorBoundary fallback={<div>错误:{todos.error.message}</div>}>
      <Suspense fallback={<div>加载中...</div>}>
        <div>
          <div>待办事项:</div>
          <ul>
            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
          </ul>
        </div>
      </Suspense>
    </ErrorBoundary>
  )
}
import { useQuery } from '@tanstack/solid-query'

function App() {
  const todos = useQuery(() => ({
    queryKey: 'todos',
    queryFn: async () => {
      const response = await fetch('/api/todos')
      if (!response.ok) {
        throw new Error('获取待办事项失败')
      }
      return response.json()
    },
    throwOnError: true,
  }))

  return (
    <ErrorBoundary fallback={<div>错误:{todos.error.message}</div>}>
      <Suspense fallback={<div>加载中...</div>}>
        <div>
          <div>待办事项:</div>
          <ul>
            <For each={todos.data}>{(todo) => <li>{todo.title}</li>}</For>
          </ul>
        </div>
      </Suspense>
    </ErrorBoundary>
  )
}

useQuery 参数

  • 查询选项 - Accessor<QueryOptions>

    • queryKey: unknown[]
      • 必需
      • 此查询使用的查询键。
      • 查询键将被哈希为一个稳定的哈希值。有关更多信息,请参阅查询键
      • 当此键更改时,查询将自动更新(只要 enabled 未设置为 false)。
    • queryFn: (context: QueryFunctionContext) => Promise<TData>
      • 必需,但仅当未定义默认查询函数时 有关更多信息,请参阅默认查询函数
      • 查询将用于请求数据的函数。
      • 接收一个 QueryFunctionContext
      • 必须返回一个 Promise,该 Promise 将解析数据或抛出错误。数据不能是 undefined
    • enabled: boolean
      • 将此项设置为 false 以禁用此查询的自动运行。
      • 可用于依赖查询以获取更多信息。
    • select: (data: TData) => unknown
      • 可选
      • 此选项可用于转换或选择查询函数返回的数据的一部分。它会影响返回的 data 值,但不会影响存储在查询缓存中的内容。
      • select 函数仅在 data 更改或 select 函数本身的引用更改时才会运行。要进行优化,请将函数包装在 useCallback 中。
    • placeholderData: TData | (previousValue: TData | undefined; previousQuery: Query | undefined,) => TData
      • 可选
      • 如果设置,当查询仍处于 pending 状态时,此值将用作此特定查询观察者的占位符数据。
      • placeholderData 不会持久化到缓存中
      • 如果为 placeholderData 提供一个函数,则作为第一个参数,您将收到先前监视的查询数据(如果可用),第二个参数将是完整的先前 Query 实例。
    • deferStream: boolean
      • 可选
      • 默认为 false
      • ���在服务器上使用流式传输渲染查询时适用。
      • deferStream 设置为 true 以在刷新流之前等待查询在服务器上解析。
      • 这对于在查询解析之前避免向客户端发送加载状态非常有用。
    • reconcile: false | string | ((oldData: TData | undefined, newData: TData) => TData)
      • 可选
      • 默认为 false
      • 将此项设置为字符串以根据字符串键启用查询结果之间的协调。
      • 将此项设置为一个函数,该函数接受旧数据和新数据并返回相同类型的已解析数据,以实现自定义协调逻辑。
    • gcTime: number | Infinity
      • 默认为 5 * 60 * 1000 (5 分钟) 或 SSR 期间的 Infinity
      • 未使用/非活动缓存数据在内存中保留的时间(以毫秒为单位)。当查询的缓存变为未使用或非活动状态时,该缓存数据将在此持续时间后进行垃圾回收。当指定不同的垃圾回收时间时,将使用最长的时间。
      • 注意:允许的最大时间约为 24 天。请参阅更多
      • 如果设置为 Infinity,将禁用垃圾回收
    • networkMode: 'online' | 'always' | 'offlineFirst
      • 可选
      • 默认为 'online'
      • 有关更多信息,请参阅网络模式
    • initialData: TData | () => TData
      • 可选
      • 如果设置,此值将用作查询缓存的初始数据(只要查询尚未创建或缓存)
      • 如果设置为函数,则该函数将在共享/根查询初始化期间一次调用,并应同步返回 initialData
      • 除非设置了 staleTime,否则初始数据默认情况下被视为过时。
      • initialData 会持久化到缓存中
    • initialDataUpdatedAt: number | (() => number | undefined)
      • 可选
      • 如果设置,此值将用作 initialData 本身上次更新的时间(以毫秒为单位)。
    • meta: Record<string, unknown>
      • 可选
      • 如果设置,则在查询缓存条目上存储其他信息,可以根据需要使用。它将在 query 可用的任何地方访问,并且也是提供给 queryFnQueryFunctionContext 的一部分。
    • queryKeyHashFn: (queryKey: QueryKey) => string
      • 可选
      • 如果指定,此函数用于将 queryKey 哈希为字符串。
    • refetchInterval: number | false | ((query: Query) => number | false | undefined)
      • 可选
      • 如果设置为数字,则所有查询将以毫秒为单位的此频率持续重新获取
      • 如果设置为函数,则将使用查询执行该函数以计算频率
    • refetchIntervalInBackground: boolean
      • 可选
      • 如果设置为 true,则设置为使用 refetchInterval 持续重新获取的查询将在其选项卡/窗口处于后台时继续重新获取
    • refetchOnMount: boolean | "always" | ((query: Query) => boolean | "always")
      • 可选
      • 默认为 true
      • 如果设置为 true,则如果数据已过时,查询将在挂载时重新获取。
      • 如果设置为 false,则查询在挂载时不会重新获取。
      • 如果设置为 "always",则查询将始终在挂载时重新获取。
      • 如果设置为函数,则将使用查询执行该函数以计算值
    • refetchOnWindowFocus: boolean | "always" | ((query: Query) => boolean | "always")
      • 可选
      • 默认为 true
      • 如果设置为 true,则如果数据已过时,查询将在窗口聚焦时重新获取。
      • 如果设置为 false,则查询在窗口聚焦时不会重新获取。
      • 如果设置为 "always",则查询将始终在窗口聚焦时重新获取。
      • 如果设置为函数,则将使用查询执行该函数以计算值
    • refetchOnReconnect: boolean | "always" | ((query: Query) => boolean | "always")
      • 可选
      • 默认为 true
      • 如果设置为 true,则如果数据已过时,查询将在重新连接时重新获取。
      • 如果设置为 false,则查询在重新连接时不会重新获取。
      • 如果设置为 "always",则查询将始终在重新连接时重新获取。
      • 如果设置为函数,则将使用查询执行该函数以计算值
    • retry: boolean | number | (failureCount: number, error: TError) => boolean
      • 如果为 false,则失败的查询默认情况下不会重试。
      • 如果为 true,则失败的查询将无限次重试。
      • 如果设置为数字,例如 3,则失败的查询将重试,直到失败的查询计数达到该数字。
      • 在客户端默认为 3,在服务器上默认为 0
    • retryOnMount: boolean
      • 如果设置为 false,则如果查询包含错误,则在挂载时不会重试该查询。默认为 true
    • retryDelay: number | (retryAttempt: number, error: TError) => number
      • 此函数接收一个 retryAttempt 整数和实际的 Error,并返回在下一次尝试之前应用的延迟(以毫秒为单位)。
      • 诸如 attempt => Math.min(attempt > 1 ? 2 ** attempt * 1000 : 1000, 30 * 1000) 之类的函数应用指数退避。
      • 诸如 attempt => attempt * 1000 之类的函数应用线性退避。
    • staleTime: number | Infinity
      • 可选
      • 默认为 0
      • 数据被视为过时之前的时间(以毫秒为单位)。此值仅适用于定义它的钩子。
      • 如果设置为 Infinity,则除非手动失效,否则数据不会被视为过时
    • throwOnError: undefined | boolean | (error: TError, query: Query) => boolean
      • 如果希��在渲染阶段抛出错误并传播到最近的错误边界,请将此项设置为 true
      • 将此项设置为 false 以禁用 suspense 的默认行为(即抛出错误到错误边界)。
      • 如果设置为函数,则将传递错误和查询,并且该函数应返回一个布尔值,指示是在错误边界中显示错误 (true) 还是将错误作为状态返回 (false)
  • 查询客户端 - Accessor<QueryClient>

    • 可选
    • 使用此选项可使用自定义 QueryClient。否则,将使用最近上下文中的 QueryClient。

useQuery 返回值 - Store<QueryResult<TData, TError>>

useQuery 返回一个具有以下属性的 SolidJS 存储:

  • status: QueryStatus
    • 将是:
      • pending 如果没有缓存数据并且尚未完成任何查询尝试。
      • error 如果查询尝试导致错误。相应的 error 属性包含从尝试的获取中收到的错误
      • success 如果查询已收到没有错误的响应并且已准备好显示其数据。查询上的相应 data 属性是从成功获取中收到的数据,或者如果查询的 enabled 属性设置为 false 并且尚未获取,则 data 是在初始化时提供给查询的第一个 initialData
  • isPending: boolean
    • 从上面的 status 变量派生的布尔值,为方便起见而提供。
  • isSuccess: boolean
    • 从上面的 status 变量派生的布尔值,为方便起见而提供。
  • isError: boolean
    • 从上面的 status 变量派生的布尔值,为方便起见而提供。
  • isLoadingError: boolean
    • 如果查询在首次获取时失败,则为 true
  • isRefetchError: boolean
    • 如果查询在重新获取时失败,则为 true
  • data: Resource<TData>
    • 默认为 undefined
    • 查询的最后成功解析的数据。
    • 重要提示data 属性是 SolidJS 资源。这意味着如果在 <Suspense> 组件下访问数据, 如果数据尚不可用,它将触发 Suspense 边界。
  • dataUpdatedAt: number
    • 查询最近返回 status"success" 的时间戳。
  • error: null | TError
    • 默认为 null
    • 查询的错误对象(如果引发了错误)。
  • errorUpdatedAt: number
    • 查询最近返回 status"error" 的时间戳。
  • isStale: boolean
    • 如果缓存中的数据已失效或数据早于给定的 staleTime,则为 true
  • isPlaceholderData: boolean
    • 如果显示的数据是占位符数据,则为 true
  • isFetched: boolean
    • 如果查询已获取,则为 true
  • isFetchedAfterMount: boolean
    • 如果查询在组件挂载后已获取,则为 true
    • 此属性可用于不显示任何先前缓存的数据。
  • fetchStatus: FetchStatus
    • fetching:每当 queryFn 执行时都为 true,其中包括初始 pending 以及后台重新获取。
    • paused:查询想要获取,但已 paused
    • idle:查询未获取。
    • 有关更多信息,请参阅网络模式
  • isFetching: boolean
    • 从上面的 fetchStatus 变量派生的布尔值,为方便起见而提供。
  • isPaused: boolean
    • 从上面的 fetchStatus 变量派生的布尔值,为方便起见而提供。
  • isRefetching: boolean
    • 每当后台重新获取正在进行时都为 true,其中_不_包括初始 pending
    • isFetching && !isPending 相同
  • isLoading: boolean
    • 每当查询的首次获取正在进行时都为 true
    • isFetching && isPending 相同
  • isInitialLoading: boolean
    • 已弃用
    • isLoading 的别名,将在下一个主要版本中删除。
  • failureCount: number
    • 查询的失败计数。
    • 每次查询失败时递增。
    • 查��成功时重置为 0
  • failureReason: null | TError
    • 查询重试的失败原因。
    • 查询成功时重置为 null
  • errorUpdateCount: number
    • 所有错误的总和。
  • refetch: (options: { throwOnError: boolean, cancelRefetch: boolean }) => Promise<UseQueryResult>
    • 手动重新获取查询的函数。
    • 如果查询出错,则只会记录错误。如果要抛出错误,请传递 throwOnError: true 选项
    • cancelRefetch?: boolean
      • 默认为 true
        • 默认情况下,在发出新请求之前将取消当前正在运行的请求
      • 设置为 false 时,如果已有请求正在运行,则不会进行重新获取。