译零 TransZero · TanStack Query 中文文档
主站

Suspense

更新于 2026-11-02 Preact 查看英文原文 ↗

Preact Query 也可与 Preact 的 Suspense 数据拉取(Data Fetching)API 配合使用。为此,我们提供了专用的 Hook:

启用 suspense 模式后,status 状态和 error 对象将不再需要,并由 Suspense 组件(来自 preact/compat)替代(包括使用 fallback 属性,以及借助错误边界捕获错误)。有关如何配置 suspense 模式的更多信息,请参阅 重置错误边界 章节。

若希望修改(mutation)也像查询(query)一样将错误传播至最近的错误边界,你可将 throwOnError 选项设为 true。

为查询启用 suspense 模式:

TypeScript
1import { useSuspenseQuery } from '@tanstack/preact-query'2 3const { data } = useSuspenseQuery({ queryKey, queryFn })

该模式在 TypeScript 中表现良好,因为 data 被保证已定义(错误与加载状态均由 Suspense 和错误边界处理)。

但反过来说,你因此无法有条件地启用或禁用该查询。对于依赖型查询(dependent Queries),这通常并不必要,因为在 suspense 模式下,同一组件内的所有查询会按串行方式拉取。

此查询也不支持 placeholderData。

throwOnError 默认行为

默认情况下,并非所有错误都会抛出至最近的错误边界——仅当没有其他数据可展示时,错误才会被抛出。这意味着:如果某个查询曾在缓存中成功获取过数据,则即使当前数据已过期(stale),组件仍会正常渲染。因此 throwOnError 的默认值为:

Code
1throwOnError: (error, query) => typeof query.state.data === 'undefined'

由于你无法更改 throwOnError(否则可能导致 data 变为潜在的 undefined),若希望所有错误均由错误边界统一处理,需手动抛出错误:

TypeScript
1import { useSuspenseQuery } from '@tanstack/preact-query'2 3const { data, error, isFetching } = useSuspenseQuery({ queryKey, queryFn })4 5if (error && !isFetching) {6  throw error7}8 9// continue rendering data

重置错误边界

无论你在查询中使用 suspense 还是 throwOnError,都需要一种机制,让查询知晓:在发生错误并重新渲染时,你希望它重试。

查询错误可通过 QueryErrorResetBoundary 组件或 useQueryErrorResetBoundary Hook 重置。

使用组件时,它将在该组件的作用域内重置所有查询错误:

Preact 并未内置错误边界组件,但你可以借助 useErrorBoundary Hook 构建一个:

TypeScript
1import { QueryErrorResetBoundary } from '@tanstack/ppreact-query'2import { useErrorBoundary } from 'preact/hooks'3 4function ErrorBoundary({ children, onReset, fallbackRender }) {5  const [error, resetError] = useErrorBoundary()6 7  if (error) {8    return fallbackRender({9      error,10      resetErrorBoundary: () => {11        onReset()12        resetError()13      },14    })15  }16 17  return children18}19 20const App = () => (21  <QueryErrorResetBoundary>22    {({ reset }) => (23      <ErrorBoundary24        onReset={reset}25        fallbackRender={({ resetErrorBoundary }) => (26          <div>27            There was an error!28            <button onClick={() => resetErrorBoundary()}>Try again</button>29          </div>30        )}31      >32        <Page />33      </ErrorBoundary>34    )}35  </QueryErrorResetBoundary>36)

使用 Hook 时,它将在最近的 QueryErrorResetBoundary 作用域内重置所有查询错误;若未定义任何边界,则全局重置:

TypeScript
1import { useQueryErrorResetBoundary } from '@tanstack/ppreact-query'2 3const App = () => {4  const { reset } = useQueryErrorResetBoundary()5  return (6    <ErrorBoundary7      onReset={reset}8      fallbackRender={({ resetErrorBoundary }) => (9        <div>10          There was an error!11          <button onClick={() => resetErrorBoundary()}>Try again</button>12        </div>13      )}14    >15      <Page />16    </ErrorBoundary>17  )18}

渲染时拉取(Fetch-on-render) vs 边渲染边拉取(Render-as-you-fetch)

开箱即用时,Preact Query 在 suspense 模式下天然适配 渲染时拉取(Fetch-on-render) 方案,无需额外配置。这意味着:当你的组件尝试挂载时,它们会触发查询拉取并进入 suspend 状态,但仅发生在你导入并挂载这些组件之后。若你想更进一步,实现 边渲染边拉取(Render-as-you-fetch) 模型,我们建议在路由回调和/或用户交互事件中实现 预取(Prefetching),以便在组件挂载前、甚至在其父组件导入或挂载前就启动查询加载。

本页为 TanStack Query 文档(Preact 版)的非官方中文翻译,原文由上游团队维护,遵循 MIT 许可。 译文如有偏差,以英文原文为准。

译自上游 59d11de