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

重要默认值

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

开箱即用时,TanStack Query 的配置采用激进但合理的默认值。有时这些默认值会让新用户措手不及,或在用户不了解它们的情况下,使学习与调试变得困难。 请在持续学习和使用 TanStack Query 的过程中牢记以下要点:

  • 通过 useQuery 或 useInfiniteQuery 创建的查询实例默认将缓存数据视为过期。

若要更改此行为,你可以通过 staleTime 选项在全局或每个查询级别进行配置。指定更长的 staleTime 意味着查询将不那么频繁地重新拉取其数据。

  • 设置了 staleTime 的查询在该 staleTime 时长未过期前被视为新鲜。
    • 将 staleTime 设为例如 2 * 60 * 1000,可确保数据在 2 分钟内始终从缓存读取,且不会触发任何类型的重新拉取,除非该查询被手动使失效。
    • 将 staleTime 设为 Infinity,可确保在该查询被手动使失效前永不触发重新拉取。
    • 将 staleTime 设为 'static',则永不触发重新拉取,即使该查询被手动使失效。

'static' 和 Infinity 均可阻止基于过期时间的重新拉取,但 'static' 更严格:queryClient.invalidateQueries() 可使设置了 staleTime: Infinity 的查询失效,但对 staleTime: 'static' 无效。refetchOnMount、refetchOnWindowFocus 和 refetchOnReconnect 设为 "always" 的行为也会被 'static' 阻止。对于应用运行期间绝不会变更的数据(如启动时获取的功能开关、登录时加载的用户权限、静态参考表),请使用 'static';若你仍希望手动使失效生效,则使用 Infinity。

  • 过期查询会在后台自动重新拉取,前提是满足以下任一条件:
    • 查询的新实例挂载
    • 浏览器窗口重新获得焦点
    • 网络重新连接

推荐通过设置 staleTime 来避免过度重新拉取,但你也可以通过设置 refetchOnMount、refetchOnWindowFocus 和 refetchOnReconnect 等选项来自定义重新拉取的触发时机。

  • 查询可选择性地配置 refetchInterval,以独立于 staleTime 设置的方式定期触发重新拉取。详情请参阅 轮询(Polling)。

  • 当查询结果不再有 useQuery、useInfiniteQuery 或查询观察者(query observer)的活跃实例时,该结果会被标记为“非活跃”,并保留在缓存中,以便后续可能再次使用。

  • 默认情况下,“非活跃”查询将在 5 分钟后被垃圾回收。

    若要更改此行为,你可以将查询的默认 gcTime 修改为除 5 * 60 * 1000 毫秒以外的其他值。

  • 失败的查询会静默重试 3 次,并采用指数退避延迟,之后才捕获错误并在 UI 中显示。

    若要更改此行为,你可以将查询的默认 retry 和 retryDelay 选项修改为除 3 和默认指数退避函数以外的其他值。

  • 查询结果默认采用结构共享(structural sharing),以检测数据是否真正发生变化;若未变化,则数据引用保持不变,从而更好地支持值稳定化。如果你对此概念不熟悉,也无需担心!99.9% 的情况下你无需禁用此功能,它能在零成本的前提下提升应用性能。

结构共享仅适用于 JSON 兼容的值;其他任何值类型均始终被视为已变更。例如,若因响应体过大而引发性能问题,可通过 config.structuralSharing 标志禁用此功能。若你的查询响应中包含非 JSON 兼容的值,但仍需检测数据是否变更,可提供自定义函数作为 config.structuralSharing,用于根据旧响应与新响应计算一个值,并按需保留引用。