React Query:什么是 `staleTime`,以及你为何需要关心它?
I’m happy to translate the article for you, but I need the full text you’d like translated. Could you please paste the content (or the portion you want translated) here? I’ll keep the source line and all formatting exactly as you requested.
什么是 “Stale”?
把它想象成 冰箱里的牛奶。
- 新鲜牛奶 – 你刚买的,信任它,毫不犹豫地喝下。
- 陈旧牛奶 – 放在那里有一段时间了;它 可能 仍然可以喝,但你可能会想检查一下或换一瓶。
React Query 对获取的数据的处理方式相同:
- 新鲜数据 – “我刚拿到它,不需要再获取。”
- 陈旧数据 – “这 可能 已经过时。我会在有机会时重新获取。”
重要: 陈旧数据仍然会从缓存中 显示 给用户。React Query 不会显示加载旋转图标——它会在后台悄悄重新获取,并且只有在数据有变化时才更新 UI。
默认行为(staleTime = 0)
默认情况下,staleTime 为 0。这意味着 数据一被缓存,React Query 就会将其标记为陈旧。
所以即使你在 1 秒前获取了图书列表,React Query 仍会认为:“这可能已经过时,让我重新获取一下。”
React Query 实际上何时重新获取过期数据?
重新获取仅在特定 触发条件 下发生:
| 触发条件 | 会发生什么 |
|---|---|
| 窗口重新聚焦 | 你切换到另一个标签页,然后返回 |
| 组件挂载 | 使用该查询的组件挂载/重新挂载 |
| 网络重新连接 | 你离线后重新上线 |
常见误解
“移动鼠标会触发重新获取吗?”
不是! 只有切换到其他标签页再返回(窗口重新聚焦)才会触发。如果你在同一个标签页停留 30 分钟,除非上述触发条件之一出现,否则不会重新获取。
设置 staleTime:真实示例
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 1000 * 60 * 5, // 5 minutes
},
},
});
function App() {
return (
<QueryClientProvider client={queryClient}>
{/* Your app components */}
</QueryClientProvider>
);
}
使用此配置:
- 用户访问页面 → React Query 从 API 获取图书。
- 用户切换标签页并在 2 分钟后返回 → 数据仍然 新鲜。不会重新获取;结果会立即从缓存中返回。
- 用户在 7 分钟后返回 → 数据已 过期。React Query 在后台重新获取,如果有新数据,UI 将会更新。
staleTime vs cacheTime (gcTime) — 不要混淆它们!
| staleTime | gcTime(原 cacheTime) | |
|---|---|---|
| 它控制什么 | 数据被视为 新鲜 的时长 | 未使用 的缓存数据在内存中保留的时长 |
| 默认值 | 0(立即过期) | 5 minutes(5 分钟) |
| 过期后 | 数据被标记为过期;在下次触发时重新获取 | 数据被垃圾回收(从缓存中移除) |
可以这样理解:
staleTime= “我应该信任这条数据多久?”gcTime= “在没有组件使用后,我应该在内存中保留这条数据多久?”
快速可视时间线
Fetch happens at 0:00
|
|-- 0:00 to 5:00 → Data is FRESH (no refetch, served from cache)
|-- 5:00+ → Data is STALE (refetch on next trigger)
|
|-- If no component uses this data for 5 min → cache is GARBAGE COLLECTED
每个查询的 staleTime
您也可以在单个查询上设置 staleTime,而不是全局设置:
// 此特定查询在 10 分钟内保持新鲜
const { data } = useQuery({
queryKey: ["books", id],
queryFn: () => fetchBook(id),
staleTime: 1000 * 60 * 10, // 10 minutes
});
这会覆盖全局默认,仅针对这个查询生效。
TL;DR
staleTime = 0(默认):数据立即变为陈旧,每次触发都会重新获取。staleTime = 1000 * 60 * 5:数据在 5 分钟内保持新鲜,避免在此期间进行不必要的 API 调用。- 陈旧的数据仍然会从缓存中 显示——重新获取在后台静默进行。
- 重新获取的触发条件:窗口聚焦、组件挂载、网络重新连接——不包括鼠标移动。
staleTime(新鲜度)和gcTime(缓存生命周期)是不同的概念。
祝编码愉快!