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

迁移到 TanStack Query v5

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

破坏性变更

v5 是一个主版本,因此存在一些你需要留意的破坏性变更:

仅支持单一签名:一个对象

useQuery 及其相关 Hook 过去在 TypeScript 中拥有多个重载:即函数可被调用的不同方式。这不仅在类型层面难以维护,还需要运行时检查来判断第一个和第二个参数的类型,从而正确地构造选项。

现在我们仅支持对象格式。

TypeScript
1useQuery(key, fn, options) // [!code --]2useQuery({ queryKey, queryFn, ...options }) // [!code ++]3useInfiniteQuery(key, fn, options) // [!code --]4useInfiniteQuery({ queryKey, queryFn, ...options }) // [!code ++]5useMutation(fn, options) // [!code --]6useMutation({ mutationFn, ...options }) // [!code ++]7useIsFetching(key, filters) // [!code --]8useIsFetching({ queryKey, ...filters }) // [!code ++]9useIsMutating(key, filters) // [!code --]10useIsMutating({ mutationKey, ...filters }) // [!code ++]
TypeScript
1queryClient.isFetching(key, filters) // [!code --]2queryClient.isFetching({ queryKey, ...filters }) // [!code ++]3queryClient.getQueriesData(key, filters) // [!code --]4queryClient.getQueriesData({ queryKey, ...filters }) // [!code ++]5queryClient.setQueriesData(key, updater, filters, options) // [!code --]6queryClient.setQueriesData({ queryKey, ...filters }, updater, options) // [!code ++]7queryClient.removeQueries(key, filters) // [!code --]8queryClient.removeQueries({ queryKey, ...filters }) // [!code ++]9queryClient.resetQueries(key, filters, options) // [!code --]10queryClient.resetQueries({ queryKey, ...filters }, options) // [!code ++]11queryClient.cancelQueries(key, filters, options) // [!code --]12queryClient.cancelQueries({ queryKey, ...filters }, options) // [!code ++]13queryClient.invalidateQueries(key, filters, options) // [!code --]14queryClient.invalidateQueries({ queryKey, ...filters }, options) // [!code ++]15queryClient.refetchQueries(key, filters, options) // [!code --]16queryClient.refetchQueries({ queryKey, ...filters }, options) // [!code ++]
TypeScript
1queryCache.find(key, filters) // [!code --]2queryCache.find({ queryKey, ...filters }) // [!code ++]3queryCache.findAll(key, filters) // [!code --]4queryCache.findAll({ queryKey, ...filters }) // [!code ++]

命令式 QueryClient 方法

随着 queryClient.query 和 queryClient.infiniteQuery 的引入,这些方法已被弃用,并将在 v6 中移除。

如果你是从 v4 或更早版本升级而来:

TypeScript
1queryClient.fetchQuery(key, fn, options) // [!code --]2queryClient.query({ queryKey: key, queryFn: fn, ...options }) // [!code ++]3queryClient.fetchInfiniteQuery(key, fn, options) // [!code --]4queryClient.infiniteQuery({5  queryKey: key,6  queryFn: fn,7  ...options,8}) // [!code ++]9 10queryClient.prefetchQuery(key, fn, options) // [!code --]11queryClient.query({ queryKey: key, queryFn: fn, ...options }).catch(noop) // [!code ++]12 13queryClient.prefetchInfiniteQuery(key, fn, options) // [!code --]14queryClient15  .infiniteQuery({ queryKey: key, queryFn: fn, ...options })16  .catch(noop) // [!code ++]17 18queryClient.ensureQueryData(key, options) // [!code --]19queryClient.query({ queryKey: key, ...options, staleTime: 'static' }) // [!code ++]20 21queryClient.ensureInfiniteQueryData(key, options) // [!code --]22queryClient.infiniteQuery({ queryKey: key, ...options, staleTime: 'static' }) // [!code ++]

如果你正在更新较旧的 v5 代码,则与上述相同,只需保留单个选项对象即可。

queryClient.getQueryData 现在仅接受 queryKey 作为参数

queryClient.getQueryData 的参数已更改为仅接受一个 queryKey。

TypeScript
1queryClient.getQueryData(queryKey, filters) // [!code --]2queryClient.getQueryData(queryKey) // [!code ++]

queryClient.getQueryState 现在仅接受 queryKey 作为参数

queryClient.getQueryState 的参数已更改为仅接受一个 queryKey。

TypeScript
1queryClient.getQueryState(queryKey, filters) // [!code --]2queryClient.getQueryState(queryKey) // [!code ++]

代码迁移工具(Codemod)

为简化移除重载的迁移过程,v5 提供了一个代码迁移工具(codemod)。

该 codemod 是尽最大努力协助你完成此破坏性变更的迁移。请务必仔细审查生成的代码!此外,某些边界情况无法被 codemod 自动识别,请留意控制台输出的日志。

若要对 .js 或 .jsx 文件运行该 codemod,请使用以下命令:

Code
1npx jscodeshift@latest ./path/to/src/ \2  --extensions=js,jsx \3  --transform=./node_modules/@tanstack/react-query/build/codemods/v5/remove-overloads/remove-overloads.cjs

若要对 .ts 或 .tsx 文件运行该 codemod,请使用以下命令:

Code
1npx jscodeshift@latest ./path/to/src/ \2  --extensions=ts,tsx \3  --parser=tsx \4  --transform=./node_modules/@tanstack/react-query/build/codemods/v5/remove-overloads/remove-overloads.cjs

请注意:对于 TypeScript,你必须使用 tsx 作为解析器;否则 codemod 将无法正确应用!

注意: 应用 codemod 可能会破坏你的代码格式,因此请务必在应用 codemod 后运行 prettier 和/或 eslint!

关于 codemod 工作原理的几点说明:

  • 通常,我们首先寻找理想情况:即第一个参数是一个对象字面量表达式,且其中包含 "queryKey" 或 "mutationKey" 属性(取决于当前转换的是哪个 Hook/方法调用)。如果满足该条件,说明你的代码已符合新签名,codemod 将不会改动它。🎉
  • 如果不满足上述条件,codemod 将检查第一个参数是否为数组字面量表达式,或是否为引用了数组字面量表达式的标识符。若是,则 codemod 会将其包裹进一个对象字面量表达式中,并作为第一个参数。
  • 如果能推断出对象参数的结构,codemod 将尝试将已存在的属性复制到新创建的对象中。
  • 如果 codemod 无法推断出用法,它将在控制台输出一条提示信息,其中包含该用法所在的文件名和行号。此时你需要手动完成迁移。
  • 如果转换过程中发生错误,你也会在控制台看到提示信息。该信息将通知你发生了意外情况,请手动完成迁移。

useQuery(及 QueryObserver)上的回调已被移除

onSuccess、onError 和 onSettled 已从查询(Queries)中移除。这些回调在修改(Mutations)中未受影响。有关此项变更的动机以及替代方案,请参阅 此 RFC。

refetchInterval 回调函数现在仅接收 query 参数

此举统一了回调的调用方式(refetchOnWindowFocus、refetchOnMount 和 refetchOnReconnect 回调也均只接收 query 参数),并修复了当数据经 select 转换后,回调函数所面临的部分类型问题。

TypeScript
1- refetchInterval: number | false | ((data: TData | undefined, query: Query) => number | false | undefined) // [!code --]2+ refetchInterval: number | false | ((query: Query) => number | false | undefined) // [!code ++]

你仍可通过 query.state.data 访问数据,但该数据未经 select 转换。如需访问转换后的数据,你可在 query.state.data 上再次调用该转换函数。

useQuery 中的 remove 方法已被移除

此前,remove 方法用于从 queryCache 中移除查询,且不通知观察者。它最适合用于以命令式方式移除不再需要的数据,例如用户登出时。

但在查询仍处于活跃状态时执行此操作意义不大,因为下一次重新渲染将直接触发硬加载状态。

如你仍需移除某个查询,可使用 queryClient.removeQueries({queryKey: key})。

TypeScript
1const queryClient = useQueryClient()2const query = useQuery({ queryKey, queryFn })3 4query.remove() // [!code --]5queryClient.removeQueries({ queryKey }) // [!code ++]

最低要求的 TypeScript 版本现为 4.7

主要原因是 TypeScript 围绕类型推断发布了一项重要修复。更多信息请参阅此 TypeScript 问题。

useQuery 中的 isDataEqual 选项已被移除

此前,该函数用于指示查询应使用先前的 data(true)还是新数据(false)作为已解析的数据。

你可通过向 structuralSharing 传入一个函数来实现相同功能:

TypeScript
1import { replaceEqualDeep } from '@tanstack/react-query'2 3- isDataEqual: (oldData, newData) => customCheck(oldData, newData) // [!code --]4+ structuralSharing: (oldData, newData) => customCheck(oldData, newData) ? oldData : replaceEqualDeep(oldData, newData) // [!code ++]

已移除已弃用的自定义日志记录器(logger)

自定义日志记录器在 v4 中已被弃用,本版本中已彻底移除。日志记录仅在开发模式下生效,而开发模式下无需传入自定义日志记录器。

支持的浏览器

我们已更新 browserslist 配置,以生成更现代、性能更高且体积更小的打包产物。具体要求请参阅 此处。

私有类字段与方法

TanStack Query 一直为类定义了私有字段和方法,但它们实际上并非真正私有——仅在 TypeScript 中表现为私有。我们现在采用 ECMAScript 私有类特性,这意味着这些字段现在真正私有,在运行时无法从外部访问。

将 cacheTime 重命名为 gcTime

几乎所有人都会误读 cacheTime。它听起来像是“数据被缓存的时间长度”,但这是不正确的。

cacheTime 在查询仍被使用期间完全不生效。它仅在查询变为未使用后才开始计时。一旦超时,数据将被“垃圾回收”,以避免缓存无限增长。

gc 指的是“垃圾回收”时间。它略显技术化,但在计算机科学领域是一个相当 广为人知的缩写。

TypeScript
1const MINUTE = 60 * 1000;2 3const queryClient = new QueryClient({4  defaultOptions: {5    queries: {6-      cacheTime: 10 * MINUTE, // [!code --]7+      gcTime: 10 * MINUTE, // [!code ++]8    },9  },10})

useErrorBoundary 选项已重命名为 throwOnError

为使 useErrorBoundary 选项更具框架无关性,并避免与 React 中既定的 Hook 前缀“use”及组件名 ErrorBoundary 混淆,它已被重命名为 throwOnError,以更准确地反映其功能。

TypeScript:Error 现在是错误的默认类型,而非 any

尽管在 JavaScript 中你可以 throw 任意值(这使得 any 在类型上最准确),但绝大多数情况下抛出的都是 Errors(或 Error 的子类)。此项变更让大多数场景下在 TypeScript 中处理 error 字段更加便捷。

如果你希望抛出非 Error 类型的值,则现在需要自行设置泛型:

TypeScript
1useQuery<number, string>({2  queryKey: ['some-query'],3  queryFn: async () => {4    if (Math.random() > 0.5) {5      throw 'some error'6    }7    return 428  },9})

如需全局设置其他类型的错误,请参阅 TypeScript 指南。

eslint prefer-query-object-syntax 规则已被移除

由于目前唯一支持的语法是对象语法,此规则已不再需要。

移除了 keepPreviousData,改用 placeholderData 恒等函数(identity function)

我们已移除 keepPreviousData 选项及 isPreviousData 标志,因为它们的功能与 placeholderData 及 isPlaceholderData 标志基本重复。

为实现与 keepPreviousData 相同的功能,我们已将前一个查询的 data 作为参数传入 placeholderData(该函数接受一个恒等函数)。因此你只需向 placeholderData 提供一个恒等函数,或直接使用 TanStack Query 提供的 keepPreviousData 函数即可。

此处需注意:useQueries 不会在 placeholderData 函数中接收到 previousData 作为参数。这是因为以数组形式传入的查询具有动态性,可能导致占位数据与 queryFn 返回结果的结构不同。

TypeScript
1import {2   useQuery,3+  keepPreviousData // [!code ++]4} from "@tanstack/react-query";5 6const {7   data,8-  isPreviousData, // [!code --]9+  isPlaceholderData, // [!code ++]10} = useQuery({11  queryKey,12  queryFn,13- keepPreviousData: true, // [!code --]14+ placeholderData: keepPreviousData // [!code ++]15});

在 TanStack Query 的上下文中,“恒等函数”指始终返回其输入参数(即 data)且不做任何更改的函数。

TypeScript
1useQuery({2  queryKey,3  queryFn,4  placeholderData: (previousData, previousQuery) => previousData, // identity function with the same behavior as `keepPreviousData`5})

不过,此项变更也有一些需要注意的限制:

  • placeholderData 总是将你置于 success 状态,而 keepPreviousData 则提供前一个查询的状态。该状态可能是 error(例如:我们已成功获取数据,随后后台重新拉取时发生错误)。但该错误本身并未共享,因此我们决定沿用 placeholderData 的行为。
  • keepPreviousData 提供前一个数据的 dataUpdatedAt 时间戳,而使用 placeholderData 时,dataUpdatedAt 将保持为 0。如果你希望持续在屏幕上显示该时间戳,这可能会带来困扰。但你可通过 useEffect 绕过此限制。
TypeScript
1  const [updatedAt, setUpdatedAt] = useState(0)2 3  const { data, dataUpdatedAt } = useQuery({4    queryKey: ['projects', page],5    queryFn: () => fetchProjects(page),6  })7 8  useEffect(() => {9    if (dataUpdatedAt > updatedAt) {10      setUpdatedAt(dataUpdatedAt)11    }12  }, [dataUpdatedAt])

窗口焦点重新拉取不再监听 focus 事件

现在仅使用 visibilitychange 事件。这是因为目前我们仅支持原生支持 visibilitychange 事件的浏览器。此举修复了 此处列出的 大量问题。

网络状态不再依赖 navigator.onLine 属性

navigator.onLine 在基于 Chromium 的浏览器中表现不佳。围绕该属性存在 大量问题,导致查询被错误地标记为 offline。

为规避此问题,我们现在始终以 online: true 为初始状态,并仅监听 online 和 offline 事件来更新网络状态。

此举应能降低误判为离线的概率,但可能意味着对通过 Service Worker 加载的离线应用而言,会出现误判为在线的情况(此类应用即使无互联网连接也可正常工作)。

移除了自定义 context 属性,改用自定义 queryClient 实例

在 v4 版本中,我们引入了向所有 react-query Hook 传入自定义 context 的能力。这使得在使用微前端(MicroFrontends)时能够实现恰当的隔离。

然而,context 是一个仅限 React 的特性。context 所做的全部工作就是让我们能够访问 queryClient。我们可以通过直接传入自定义 queryClient 的方式来实现相同的隔离效果。
这反过来将使其他框架也能以与框架无关的方式获得相同的功能。

TypeScript
1import { queryClient } from './my-client'2 3const { data } = useQuery(4  {5    queryKey: ['users', id],6    queryFn: () => fetch(...),7-   context: customContext // [!code --]8  },9+  queryClient, // [!code ++]10)

移除了 refetchPage,改用 maxPages

在 v4 中,我们引入了通过 refetchPage 函数为无限查询(infinite queries)指定需重新拉取(refetch)页数的能力。

然而,重新拉取所有页面可能导致 UI 不一致。此外,该选项(例如在 queryClient.refetchQueries 上)虽已存在,但仅对无限查询生效,对“普通”查询无效。

v5 版本为无限查询新增了一个 maxPages 选项,用于限制查询数据中存储及重新拉取的页数。这一新特性在规避 refetchPage 页面功能相关问题的同时,覆盖了其最初设计所针对的所有使用场景。

新的 dehydrate API

可传入 dehydrate 的选项已被简化。查询(queries)和修改(mutations)始终按默认函数实现进行脱水(dehydrated)。若要更改此行为,不再使用已移除的布尔型选项 dehydrateMutations 和 dehydrateQueries,而是应分别实现函数形式的等效选项 shouldDehydrateQuery 或 shouldDehydrateMutation。若希望完全禁用查询/修改的注水(hydration),请传入 () => false。

TypeScript
1- dehydrateMutations?: boolean // [!code --]2- dehydrateQueries?: boolean // [!code --]

无限查询现在必须提供 initialPageParam

此前,我们将 undefined 作为 pageParam 传入 queryFn,你可以在 queryFn 的函数签名中为 pageParam 参数指定默认值。这种做法的缺点在于会将 undefined 存入 queryCache,而 queryCache 是不可序列化的。

取而代之的是,你现在必须显式地向无限查询选项传入 initialPageParam。该值将被用作第一页的 pageParam:

TypeScript
1useInfiniteQuery({2   queryKey,3-  queryFn: ({ pageParam = 0 }) => fetchSomething(pageParam), // [!code --]4+  queryFn: ({ pageParam }) => fetchSomething(pageParam), // [!code ++]5+  initialPageParam: 0, // [!code ++]6   getNextPageParam: (lastPage) => lastPage.next,7})

已移除无限查询的手动模式

此前,我们允许通过直接向 fetchNextPage 或 fetchPreviousPage 传入 pageParam 值,来覆写 getNextPageParam 或 getPreviousPageParam 返回的 pageParams。该功能在重新拉取(refetch)时完全无法工作,且鲜为人知、极少使用。这也意味着 getNextPageParam 现在已成为无限查询的必需项。

从 getNextPageParam 或 getPreviousPageParam 返回 null 现在表示无后续页面可用

在 v4 中,你需要显式返回 undefined 来表明无后续页面可用。我们已将该判断条件扩展为同时支持 null。

服务端不再重试

在服务端,retry 现在默认为 0,而非 3。对于预取(prefetching),我们一直默认采用 0 次重试;但由于启用了 suspense 的查询现在也可直接在服务端执行(得益于 React 18),我们必须确保服务端完全不进行重试。

status: loading 已更改为 status: pending,isLoading 已更改为 isPending,isInitialLoading 现已重命名为 isLoading

loading 状态已重命名为 pending,同理,派生出的 isLoading 标志也已重命名为 isPending。

对于修改(mutations),status 也已从 loading 更改为 pending,且 isLoading 标志已更改为 isPending。

最后,我们为查询(queries)新增了一个派生的 isLoading 标志,其实现为 isPending && isFetching。这意味着 isLoading 和 isInitialLoading 表达相同含义,但 isInitialLoading 现已弃用,并将在下一个主版本中移除。

如需了解此项变更背后的考量,请参阅 v5 路线图讨论。

hashQueryKey 已重命名为 hashKey

因为它不仅会对修改键(mutation keys)进行哈希运算,还可用于 predicate 函数中(即 useIsMutating 和 useMutationState 的 predicate 函数),而这些函数接收的是修改(mutations)。

最低所需 React 版本现已升至 18.0

React Query v5 要求 React 18.0 或更高版本。这是因为我们使用了仅在 React 18.0 及以上版本中才提供的新 useSyncExternalStore Hook。此前,我们一直依赖 React 提供的 shim。

已从 QueryClientProvider 中移除 contextSharing 属性

此前,你可以使用 contextSharing 属性,在整个 window 范围内共享首个(且至少一个)查询客户端(query client)上下文实例。这确保了即使 TanStack Query 被用于不同代码包或微前端中,它们也都会使用同一上下文实例,不受模块作用域影响。

随着 v5 中自定义上下文属性(custom context prop)的移除,请参阅 移除自定义上下文属性,改用自定义 queryClient 实例 一节。若你希望在整个应用的多个包之间共享同一个查询客户端,可直接传入一个共享的自定义 queryClient 实例。

不再将 unstable_batchedUpdates 用作 React 和 React Native 中的批处理函数(batching function)

由于 unstable_batchedUpdates 函数在 React 18 中为空操作(noop),它将不再被自动设为 react-query 中的批处理函数。

如果你所用的框架支持自定义批处理函数,可通过调用 notifyManager.setBatchNotifyFunction 向 TanStack Query 显式声明。

例如,以下是在 solid-query 中设置批处理函数的方式:

TypeScript
1import { notifyManager } from '@tanstack/query-core'2import { batch } from 'solid-js'3 4notifyManager.setBatchNotifyFunction(batch)

注水(Hydration)API 变更

为更好支持并发特性(concurrent features)和过渡(transitions),我们对注水 API 做了一些调整。Hydrate 组件已重命名为 HydrationBoundary,useHydrate Hook 已被移除。

HydrationBoundary 不再注水修改(mutations),仅注水查询(queries)。若需注水修改,请使用底层 hydrate API 或 persistQueryClient 插件。

最后,从技术细节看,查询被注水的时机发生了细微变化:新查询仍在渲染阶段(render phase)完成注水,以保证 SSR 正常工作;而已存在于缓存中的查询,则改在 effect 中完成注水(前提是其数据比缓存中现有数据更新)。如果你像通常那样仅在应用启动时执行一次注水,此变更不会对你造成影响;但如果你使用服务端组件(Server Components),并在页面导航时向下传递新鲜数据用于注水,则可能观察到页面先短暂显示旧数据,随后立即重新渲染。

此项变更在技术上属于破坏性变更(breaking change),其目的在于避免在页面过渡(page transition)尚未完全提交前,就过早更新 当前 页面上的内容。你无需为此采取任何操作。

TypeScript
1- import { Hydrate } from '@tanstack/react-query' // [!code --]2+ import { HydrationBoundary } from '@tanstack/react-query' // [!code ++]3 4 5- <Hydrate state={dehydratedState}> // [!code --]6+ <HydrationBoundary state={dehydratedState}> // [!code ++]7  <App />8- </Hydrate> // [!code --]9+ </HydrationBoundary> // [!code ++]

查询默认值(Query defaults)变更

queryClient.getQueryDefaults 现在会合并所有匹配的注册项,而非仅返回首个匹配的注册项。

因此,对 queryClient.setQueryDefaults 的调用现在应按 递增 的特异性顺序排列。
也就是说,注册应从 最通用的键 开始,逐步过渡到 最不通用的键。

例如:

TypeScript
1+ queryClient.setQueryDefaults(['todo'], {   // [!code ++]2+   retry: false,  // [!code ++]3+   staleTime: 60 * 1000,  // [!code ++]4+ })  // [!code ++]5queryClient.setQueryDefaults(['todo', 'detail'], {6+   retry: true,  // [!code --]7  retryDelay: 1000,8  staleTime: 10 * 1000,9})10- queryClient.setQueryDefaults(['todo'], { // [!code --]11-   retry: false, // [!code --]12-   staleTime: 60 * 1000, // [!code --]13- }) // [!code --]

请注意,在此特定示例中,为抵消更通用注册项所继承的 retry: false,已在 ['todo', 'detail'] 注册项中添加了 retry: true。为维持原有行为所需的具体变更,取决于你的默认配置。

新特性 🚀

v5 还带来了以下新特性:

简化版乐观更新(optimistic updates)

我们提供了一种新的、更简化的乐观更新方式,利用 useMutation 返回的 variables:

TypeScript
1const queryInfo = useTodos()2const addTodoMutation = useMutation({3  mutationFn: (newTodo: string) => axios.post('/api/data', { text: newTodo }),4  onSettled: () => queryClient.invalidateQueries({ queryKey: ['todos'] }),5})6 7if (queryInfo.data) {8  return (9    <ul>10      {queryInfo.data.items.map((todo) => (11        <li key={todo.id}>{todo.text}</li>12      ))}13      {addTodoMutation.isPending && (14        <li key={String(addTodoMutation.submittedAt)} style={{ opacity: 0.5 }}>15          {addTodoMutation.variables}16        </li>17      )}18    </ul>19  )20}

此处,我们仅在修改运行期间改变 UI 外观,而非直接向缓存写入数据。这种方式最适合仅需在一个位置展示乐观更新的场景。更多详情,请参阅 乐观更新文档。

带新 maxPages 选项的受限无限查询(Limited, Infinite Queries)

当需要无限滚动(infinite scroll)或分页(pagination)时,无限查询非常有用。
然而,拉取的页面越多,内存消耗越大,且查询重新拉取过程也会变慢,因为所有页面均需按顺序重新拉取。

v5 为无限查询新增了 maxPages 选项,允许开发者限制查询数据中存储及后续重新拉取的页面数量。
你可以根据所需的用户体验(UX)和重新拉取性能,灵活调整 maxPages 的值。

注意:无限列表必须支持双向滚动,这要求同时定义 getNextPageParam 和 getPreviousPageParam。

无限查询可预取多页

无限查询可像普通查询一样被预取(prefetch)。默认情况下,仅预取查询的第一页,并将其存储在给定的 QueryKey 下。若需预取多于一页的内容,可使用 pages 选项。更多详情,请参阅 预取指南。

新增 combine 选项(适用于 useQueries)

更多详情请参阅 useQueries 文档。

实验性 fine grained storage persister

更多详情请参阅 experimental_createPersister 文档。

类型安全的查询选项(Query Options)创建方式

更多详情请参阅 TypeScript 文档。

新增 Suspense 相关 Hook

在 v5 中,数据获取的 Suspense 终于成为“稳定”特性。我们新增了专用的 useSuspenseQuery、useSuspenseInfiniteQuery 和 useSuspenseQueries Hook。借助这些 Hook,data 在类型层面将永远不会再是潜在的 undefined:

JavaScript
1const { data: post } = useSuspenseQuery({2  // ^? const post: Post3  queryKey: ['post', postId],4  queryFn: () => fetchPost(postId),5})

查询 Hook 上的实验性 suspense: boolean 标志已被移除。

更多详情请参阅 Suspense 文档。

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

译自上游 59d11de