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

渲染优化

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

React Query 会自动应用若干优化措施,确保你的组件仅在真正需要时才重新渲染。具体通过以下方式实现:

结构共享(structural sharing)

React Query 使用一种称为“结构共享”的技术,以尽可能在多次渲染之间保持对象引用不变。如果数据是通过网络拉取的,通常你会因对响应进行 JSON 解析而获得一个全新的引用。但 React Query 会在数据 完全未发生变化 时保留原始引用;若仅部分数据变更,则仅替换变更的部分,其余部分仍复用原有引用。

注意:该优化仅在 queryFn 返回符合 JSON 规范的数据时生效。你可通过全局设置 structuralSharing: false,或为单个查询单独设置该选项来禁用它;你也可以传入自定义函数来实现自己的结构共享逻辑。

引用稳定性(referential identity)

useQuery、useInfiniteQuery、useMutation 返回的顶层对象,以及 useQueries 返回的数组,均不保证引用稳定——每次渲染都会生成新引用。但这些 Hook 返回的 data 属性会尽可能保持引用稳定。

跟踪属性(tracked properties)

React Query 仅在 useQuery 返回的某个属性被组件“实际使用”时,才触发重新渲染。该机制基于 Proxy 对象 实现。这可避免大量不必要的重新渲染,例如 isFetching 或 isStale 等属性可能频繁变化,但组件并未使用它们。

你可以通过手动设置 notifyOnChangeProps,在全局或单个查询层面定制该行为。若要彻底禁用此功能,可将 notifyOnChangeProps: 'all' 设为 true。

注意:Proxy 的 get 拦截器会在访问属性时触发,无论你是通过解构还是直接访问。若使用对象剩余属性解构(object rest destructuring),该优化将失效。我们提供了一条 lint 规则 来防范这一陷阱。

select

你可以使用 select 选项,指定组件需订阅的数据子集。这对高度优化的数据转换或避免不必要重新渲染非常有用。

JavaScript
1export const useTodos = (select) => {2  return useQuery({3    queryKey: ['todos'],4    queryFn: fetchTodos,5    select,6  })7}8 9export const useTodoCount = () => {10  return useTodos((data) => data.length)11}

使用 useTodoCount 自定义 Hook 的组件,仅在 todos 数组长度变化时重新渲染;若某个 todo 的 name 发生变化,则 不会 触发重新渲染。

注意:select 作用于已成功缓存的数据,不适用于抛出错误。错误的唯一信源是 queryFn;若 select 函数返回错误,则 data 将变为 undefined,且 isSuccess 将变为 true。如需让查询在数据异常时失败,请在 queryFn 中处理错误;若错误与缓存无关,则应在查询 Hook 外部处理。

记忆化(memoization)

select 函数仅在以下任一条件满足时重新执行:

  • select 函数自身发生引用变化
  • data 发生变化

这意味着上例中内联定义的 select 函数将在每次渲染时执行。为避免此问题,你可将 select 函数包裹在 useCallback 中,或将其提取为一个无依赖的稳定函数引用:

JavaScript
1// wrapped in useCallback2export const useTodoCount = () => {3  return useTodos(useCallback((data) => data.length, []))4}
JavaScript
1// extracted to a stable function reference2const selectTodoCount = (data) => data.length3 4export const useTodoCount = () => {5  return useTodos(selectTodoCount)6}

延伸阅读

如需深入了解上述主题,请阅读 TkDodo 撰写的深度指南:React Query 渲染优化。如需掌握 select 选项的最佳实践,请参阅:React Query 选择器,全面增强版

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

译自上游 59d11de