React Query中staleTime与cacheTime区别及缓存正确配置方法
问题成因
先明确两个配置的底层运行规则,所有异常表现本质都是对规则理解偏差导致的:
staleTime控制数据的「新鲜时长」,计时起点是查询最后一次成功返回响应的时间。新鲜状态的数据不会在任何自动触发场景下发起重请求,包括组件重挂载、窗口聚焦、网络重连,只要数据新鲜,直接读取缓存返回。只有过了staleTime的数据被标记为「过期(stale)」后,遇到上述触发场景才会发起后台重请求。注意:数据过期后不会自动发请求,必须有对应的触发时机才会发起调用。cacheTime控制缓存的「无引用留存时长」,计时起点是所有使用该查询key的组件全部完成卸载的时刻。只要还有任意一个组件在使用这个查询,缓存就会永久留存,和cacheTime配置无关。缓存被清理后,下次组件再挂载调用该查询,会被判定为全新查询,直接发请求加载。
你遇到的两个异常的具体原因:
- 仅配置staleTime为2分钟时,超过2分钟不触发API调用:React Query默认的cacheTime是5分钟,远长于你设置的2分钟staleTime。过了2分钟后数据确实变为过期状态,但如果你测试时没有触发重请求的时机(比如组件一直保持挂载没切走、没有切换窗口焦点、没有断网重连),过期数据不会主动触发请求,自然不会有API调用。
- 仅配置cacheTime为2分钟时,每次组件挂载卸载都触发API调用:React Query默认的staleTime是0,也就是说请求返回的瞬间数据就会被标记为过期状态。这种情况下哪怕缓存里还有数据,组件每次重挂载时,React Query检测到过期缓存,都会立刻触发后台重请求;如果卸载后等待时间超过2分钟,缓存会被直接清理,下次挂载会作为全新查询发起请求,看起来就像每次挂载卸载都在调用API。
你当前把staleTime和cacheTime都设为2分钟的写法还存在边界bug:如果组件在数据返回后30秒就卸载,cacheTime会从卸载时刻开始算2分钟,也就是到数据返回后的150秒才清理缓存,但数据在120秒的时候就已经过期了。如果你在120秒-150秒之间重新挂载组件,React Query会返回缓存的旧数据,同时立刻发起后台重请求,不符合你“2分钟内完全不发请求”的需求。
最佳实现方案
要满足「首次请求成功后2分钟内,无论组件挂载/卸载都不重复发请求」的需求,核心是保证2分钟的时间窗口内,数据始终处于新鲜状态,且缓存不会被提前清理,配置逻辑如下:
- 将
staleTime设为120000(2分钟),保证2分钟内数据始终为新鲜状态,不会触发任何自动重请求 - 将
cacheTime设为大于等于120000的值即可,不需要和staleTime保持一致,直接用默认的5分钟(300000)就足够,避免组件在新鲜窗口期内卸载导致缓存被提前清理 - 如果你希望过了2分钟的新鲜期后,也不要在窗口聚焦、网络重连时自动刷新,可以额外关闭对应的重请求触发开关,按需配置即可
参考配置代码:
const query = useQuery( ["getUserList"], getUserList, { staleTime: 120000, // 数据新鲜期2分钟,窗口内完全不触发自动重请求 cacheTime: 300000, // 无组件引用时缓存留存5分钟,默认值即可,保证新鲜期内缓存不丢失 // 以下配置按需开启,默认均为true // refetchOnWindowFocus: false, // 关闭窗口聚焦时的过期数据重刷 // refetchOnReconnect: false, // 关闭网络重连时的过期数据重刷 } );
这个配置下的运行逻辑完全匹配需求:
- 首次挂载组件时正常发起请求,拿到数据后开始计算2分钟新鲜期
- 2分钟内无论组件反复卸载、重挂载,都会直接读取缓存返回,不会发起任何API请求
- 超过2分钟后数据变为过期状态,只有遇到重挂载、窗口聚焦、手动refetch等触发时机时,才会发起新的请求更新缓存,之后重新开始计算2分钟的新鲜期
内容的提问来源于stack exchange,提问作者meet d
相关产品推荐
相关产品推荐

