gcTime vs staleTime 辨析

TanStack Query 中最容易混淆的两个时间参数:staleTime 控制数据"是否新鲜",gcTime 控制缓存"何时回收"。两者解决完全不同的问题。

#type / concept #status / evergreen #tech / dev / frontend #resource / react

[!info] related notes

gcTime vs staleTime 辨析

核心区别

staleTime → 数据"新不新"? → 决定是否需要重新请求
gcTime    → 缓存"留不留"? → 决定无订阅后多久清除缓存

这两个参数完全不相关,解决的是两个独立的问题。

staleTime — 数据新鲜度

语义

数据在多久内被认为是”新鲜的”。新鲜的数据不会触发后台重新请求。

组件挂载 → useQuery 检查缓存
  ├─ 缓存存在且在 staleTime 内 → 直接用缓存,不请求
  └─ 缓存不存在或已过 staleTime → 发请求(同时先显示缓存数据)

默认值

staleTime: 0  // 默认:数据一拿到就标记为 stale

常见配置

// 几乎实时的数据(股票、聊天)
staleTime: 0

// 用户信息,5 分钟内不重新请求
staleTime: 5 * 60 * 1000

// 配置数据,10 分钟
staleTime: 10 * 60 * 1000

// 几乎不变的数据(国家列表)
staleTime: Infinity  // 永远不自动请求,只手动 invalidate

触发重新请求的条件

即使在 staleTime 内,以下操作仍会触发请求:

  • 手动 invalidateQueries
  • queryKey 变化
  • 组件卸载后重新挂载(如果已过 staleTime)

gcTime — 垃圾回收时间

语义

当一个 query 的所有订阅者(useQuery 调用)都卸载后,缓存数据在内存中保留多久。

最后一个 useQuery 组件卸载
  → 等待 gcTime
  → 如果期间没有新的订阅者 → 删除缓存数据
  → 如果期间有新的订阅者 → 保留缓存

默认值

gcTime: 5 * 60 * 1000  // 默认 5 分钟(v5)
// v4 中叫 cacheTime,v5 改名为 gcTime

常见配置

// 默认行为:卸载 5 分钟后清除缓存
gcTime: 5 * 60 * 1000

// 保留更久:用户可能来回切换页面
gcTime: 30 * 60 * 1000

// 立即清除:卸载就删(不推荐,除非内存敏感)
gcTime: 0

// 永不清理:类似持久化缓存
gcTime: Infinity  // ⚠️ 内存会持续增长

对比表

维度staleTimegcTime
控制什么数据是否需要重新请求缓存数据是否保留
默认值0(立即 stale)5 分钟
影响时机组件挂载 / 窗口聚焦 / 重新连接最后一个订阅者卸载后
设为 0每次挂载都重新请求卸载后立即清除缓存
设为 Infinity永不自动请求(只手动 invalidate)缓存永不回收
v4 名称staleTimecacheTime

常见错误

混淆两者

// ❌ 以为 gcTime 控制刷新频率
useQuery({ gcTime: 10_000, ... });  // 这只控制缓存保留时间

// ✅ 用 staleTime 控制刷新频率
useQuery({ staleTime: 10_000, ... });

staleTime > gcTime

// ❌ 逻辑矛盾
useQuery({
  staleTime: 10 * 60 * 1000,   // 10 分钟内不请求
  gcTime: 1 * 60 * 1000,       // 但 1 分钟后就删缓存
});
// 结果:卸载 1 分钟后缓存被删,再挂载时又要重新请求
// staleTime 的"10 分钟不重新请求"形同虚设

// ✅ gcTime 应该 >= staleTime
useQuery({
  staleTime: 10 * 60 * 1000,
  gcTime: 30 * 60 * 1000,      // 保留 30 分钟
});

以为设了 staleTime 就不会请求

useQuery({ staleTime: 60_000 });
// 以下情况仍然会请求:
// 1. queryKey 变化
// 2. 手动 invalidateQueries
// 3. 组件首次挂载且没有缓存
// 4. 网络重连后(默认行为)

决策流程图

这个数据多久变一次?

  ├─ 几乎实时 → staleTime: 0(默认)
  ├─ 几分钟变一次 → staleTime: 2~5 分钟
  ├─ 很少变 → staleTime: 10~30 分钟
  └─ 几乎不变 → staleTime: Infinity + 手动 invalidate

用户会频繁在这页和其他页之间切换吗?

  ├─ 是 → gcTime 长一些(10~30 分钟)
  └─ 否 → gcTime 默认(5 分钟)即可
创建于 2026/7/3 更新于 2026/7/15