前端
PythonJava运维数据库
TanStack Query
TanStack Query
  • getting started
    • 快速开始
    • 开发工具
    • Typescript
    • 默认配置
    • 网络模式
  • Query
    • 查询
    • 查询键
    • 查询函数
    • 查询选项
    • 并行查询
    • 有依赖的查询
    • 查询状态指示器
    • 窗口聚焦重新获取数据
    • 禁用/暂停查询
    • 查询重试
    • 分页查询
    • 无限查询
    • 初始化查询数据
  • 占位符
  • Mutation
    • 修改 Mutations
    • 主动查询失效 Query Invalidation
    • 修改导致的失效 Invalidation From Mutations
    • 通过修改的数据更新查询内容
    • 乐观更新
  • 取消查询
  • 默认查询函数
  • 过滤器
  • Suspense
  • 缓存数据
  • Api Reference
    • QueryClient
    • QueryCache
    • MutationCache
    • QueryObserver QueriesObserver
    • InfiniteQueryObserver
    • FocusManager
    • NotifyManager
    • useQuery
    • useQueries useInfiniteQuery
    • useMutation
    • useIsFetching
    • useIsMutating
    • useMutationState
    • useSuspenseQuery
    • useSuspenseInfiniteQuery
    • useSuspenseQueries
    • QueryClientProvider
    • useQueryClient
    • queryOptions
    • infiniteQueryOptions
    • QueryErrorResetBoundary
    • useQueryErrorResetBoundary
    • hydration
由 GitBook 提供支持
在本页
  • Suspense(挂起)
  • 重置错误边界(Resetting Error Boundaries)
  • Fetch-on-render vs Render-as-you-fetch
  • 在服务器端使用 Suspense(Streaming)
  • 使用 useQuery().promise 和 React.use()(实验性)

这有帮助吗?

Suspense

sup

Suspense(挂起)

React Query 也可以与 React 的 Suspense for Data Fetching API 一起使用。对此,React Query 提供了一些专门的 Hook:

  • useSuspenseQuery

  • useSuspenseInfiniteQuery

  • useSuspenseQueries

此外,你还可以使用 useQuery().promise 和 React.use()(实验性功能)。

在 Suspense 模式下,状态(status)和错误对象(error)不再需要,它们由 React.Suspense 组件 处理(包括使用 fallback 属性提供回退 UI,并利用 React 错误边界(Error Boundaries) 捕获错误)。 请阅读 Resetting Error Boundaries 以及 Suspense 示例 了解如何正确设置 Suspense 模式。

如果你希望 Mutation(变更) 也像 Query 一样将错误抛给最近的 Error Boundary,你可以设置 throwOnError: true。


启用 Suspense 模式

import { useSuspenseQuery } from '@tanstack/react-query'

const { data } = useSuspenseQuery({ queryKey, queryFn })

在 TypeScript 中,这种方式很好用,因为 data 保证是已定义的(因为错误和加载状态已经由 Suspense 和 Error Boundary 处理)。

⚠ 注意:

  • 你 无法 动态开启/关闭该 Query(enabled 选项不可用)。

  • placeholderData 在 Suspense 模式下不可用。

  • 避免 UI 在更新时被 fallback 取代,你可以使用 startTransition 包裹 QueryKey 变化的更新。


throwOnError 的默认行为

并 不是所有错误 都会默认抛给最近的 Error Boundary,只有当 Query 没有可用数据 时,错误才会被抛出:

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

由于 throwOnError 不能被修改(否则 data 可能变为 undefined),如果你希望所有错误都被 Error Boundary 处理,你需要手动抛出错误:

import { useSuspenseQuery } from '@tanstack/react-query'

const { data, error, isFetching } = useSuspenseQuery({ queryKey, queryFn })

if (error && !isFetching) {
  throw error
}

// 继续渲染 data

重置错误边界(Resetting Error Boundaries)

无论你是 使用 Suspense 还是 设置 throwOnError,当错误发生后,你需要一种方法来 重置错误状态 并重新尝试请求数据。 React Query 提供了两种方式来 重置 Query 的错误状态:

1. QueryErrorResetBoundary 组件

该组件会 重置其内部所有 Query 的错误状态:

import { QueryErrorResetBoundary } from '@tanstack/react-query'
import { ErrorBoundary } from 'react-error-boundary'

const App = () => (
  <QueryErrorResetBoundary>
    {({ reset }) => (
      <ErrorBoundary
        onReset={reset}
        fallbackRender={({ resetErrorBoundary }) => (
          <div>
            There was an error!
            <Button onClick={() => resetErrorBoundary()}>Try again</Button>
          </div>
        )}
      >
        <Page />
      </ErrorBoundary>
    )}
  </QueryErrorResetBoundary>
)

2. useQueryErrorResetBoundary Hook

这个 Hook 会 重置最近的 QueryErrorResetBoundary 内部的错误状态,如果没有 QueryErrorResetBoundary,则会 全局重置错误状态:

import { useQueryErrorResetBoundary } from '@tanstack/react-query'
import { ErrorBoundary } from 'react-error-boundary'

const App = () => {
  const { reset } = useQueryErrorResetBoundary()
  return (
    <ErrorBoundary
      onReset={reset}
      fallbackRender={({ resetErrorBoundary }) => (
        <div>
          There was an error!
          <Button onClick={() => resetErrorBoundary()}>Try again</Button>
        </div>
      )}
    >
      <Page />
    </ErrorBoundary>
  )
}

Fetch-on-render vs Render-as-you-fetch

React Query 在 Suspense 模式下 默认使用 Fetch-on-render,这意味着:

  • 组件 在挂载时 触发数据请求。

  • 组件会 挂起(Suspend),直到数据加载完成。

如果你希望 提前加载数据,可以使用 预取(Prefetching) 技术,在 路由回调 或 用户交互事件 中 预加载 Query,从而实现 Render-as-you-fetch 模型。


在服务器端使用 Suspense(Streaming)

如果你使用 Next.js,可以使用 @tanstack/react-query-next-experimental 来支持 服务端 Suspense Streaming。 这可以让你在 客户端组件 中调用 useSuspenseQuery,并在服务器端预取数据,结果会被 流式传输(Streaming) 到客户端。

如何启用 Streaming

// app/providers.tsx
'use client'

import {
  isServer,
  QueryClient,
  QueryClientProvider,
} from '@tanstack/react-query'
import * as React from 'react'
import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'

function makeQueryClient() {
  return new QueryClient({
    defaultOptions: {
      queries: {
        // 在 SSR 场景下,通常会设置一个默认的 staleTime,避免客户端立即重新请求
        staleTime: 60 * 1000,
      },
    },
  })
}

let browserQueryClient: QueryClient | undefined = undefined

function getQueryClient() {
  if (isServer) {
    return makeQueryClient()
  } else {
    if (!browserQueryClient) browserQueryClient = makeQueryClient()
    return browserQueryClient
  }
}

export function Providers(props: { children: React.ReactNode }) {
  const queryClient = getQueryClient()

  return (
    <QueryClientProvider client={queryClient}>
      <ReactQueryStreamedHydration>
        {props.children}
      </ReactQueryStreamedHydration>
    </QueryClientProvider>
  )
}

更多信息,请查看 Next.js Suspense Streaming 示例 和 高级渲染 & Hydration 指南。


使用 useQuery().promise 和 React.use()(实验性)

上一页过滤器下一页缓存数据

最后更新于2个月前

这有帮助吗?