Skip to content

React Query 中的 staleTime 和 cacheTime

问题描述

在使用 React Query 进行数据缓存时,很多开发者对 staleTimecacheTime 的使用感到困惑。特别是当需要将 API 数据在首次获取后在缓存中保存 2 分钟,无论组件是否挂载或卸载,在这段时间内都不希望再次发起 API 请求。

解决方案

核心概念理解

staleTimecacheTime 在 React Query 中承担着不同的职责:

staleTime:数据新鲜度控制

  • 作用:决定数据在多长时间内被认为是"新鲜"的
  • 类比:类似于 HTTP 头中的 Cache-Control: max-age=120
  • 效果:在 staleTime 设置的时间内,React Query 不会发起新的网络请求
  • 默认值:0(立即变为陈旧)

cacheTime:缓存垃圾回收控制

  • 作用:决定未使用的查询数据在缓存中保存的时间
  • 效果:当查询不再被任何组件使用时(所有使用该查询的组件都已卸载),数据会在 cacheTime 设置的时间后被垃圾回收
  • 默认值:5分钟

正确的配置方式

要实现"首次获取数据后2分钟内不发起API请求"的需求,应该这样配置:

javascript
const query = useQuery(
  ["getUserList"], 
  getUserList, 
  {
    staleTime: 120000, // 数据保持新鲜2分钟
    cacheTime: 300000  // 缓存保留5分钟(默认值)
  }
);

可视化理解流程

查看数据获取流程图

常见误区澄清

重要提醒

staleTime 控制的是数据的新鲜度,而不是自动重新获取数据的时间间隔。即使数据标记为陈旧,React Query 也不会立即重新获取,除非满足特定条件(如窗口重新获得焦点、组件重新挂载等)。

如果需要定期重新获取数据,应该使用 refetchInterval

javascript
const query = useQuery(
  ["getUserList"], 
  getUserList, 
  {
    staleTime: 120000,
    refetchInterval: 120000 // 每2分钟重新获取数据
  }
);

实际应用场景

场景一:实时性要求不高的数据

javascript
// 用户配置信息,不需要频繁更新
useQuery(["userProfile"], fetchUserProfile, {
  staleTime: 5 * 60 * 1000, // 5分钟内使用缓存
  cacheTime: 30 * 60 * 1000 // 30分钟后清理缓存
});

场景二:频繁变化的实时数据

javascript
// 实时股价信息,需要频繁更新
useQuery(["stockPrice"], fetchStockPrice, {
  staleTime: 1000, // 1秒后就视为陈旧
  refetchInterval: 2000, // 每2秒重新获取
  refetchOnWindowFocus: true // 窗口聚焦时重新获取
});

最佳实践

  1. 合理设置 staleTime:根据数据的实际变化频率设置合适的过期时间
  2. cacheTime 通常无需修改:除非有特殊的内存管理需求,否则保持默认的5分钟即可
  3. 组合使用缓存策略:结合 refetchOnWindowFocusrefetchOnReconnect 等选项实现最佳用户体验
  4. 考虑用户体验:对于重要但变化不频繁的数据,设置较长的 staleTime 可以减少不必要的请求

专业建议

在开发过程中,可以使用 React Query Devtools 来直观地查看缓存的状态、数据的过期情况,这有助于更好地理解和调试缓存行为。

通过正确理解和使用 staleTimecacheTime,你可以有效地管理应用的数据缓存策略,既提升了用户体验,又减少了不必要的网络请求。