React 请求缓存方案深度解析
在开发中,避免重复的 API 请求不仅可以提升用户体验(秒开),还能显著减轻服务器负担。本文将介绍从基础到工业级的多种请求缓存方案。
方案一:基础方案(State + useEffect)
最简单的缓存思路是在组件内部或父组件中维护一个 data 状态。如果数据已存在,则不再触发请求。
tsx
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
// 只有当 user 为空时才请求
if (!user) {
fetchUser(userId).then(setUser);
}
}, [userId, user]);
return <div>{user?.name}</div>;
}缺点:缓存生命周期随组件销毁而结束,无法跨页面共享。
方案二:简单全局 Map 缓存
利用 JavaScript 模块的特性,在内存中维护一个全局对象。
tsx
const cache = new Map();
function useCachedUser(userId) {
const [data, setData] = useState(cache.get(userId));
useEffect(() => {
if (!cache.has(userId)) {
fetchUser(userId).then(res => {
cache.set(userId, res);
setData(res);
});
}
}, [userId]);
return data;
}优点:实现简单,跨组件共享。 缺点:难以处理缓存失效(过期)、不支持自动重新获取、无法感知正在进行的请求(重复请求去重)。
方案三:外部状态管理(Zustand / Redux)
通过全局状态管理库来持久化数据。
Zustand 示例
tsx
import { create } from 'zustand';
const useUserStore = create((set, get) => ({
users: {}, // { [id]: userData }
fetchUser: async (id) => {
// 检查缓存
if (get().users[id]) return;
const res = await api.getUser(id);
set((state) => ({
users: { ...state.users, [id]: res }
}));
},
}));
function UserAvatar({ id }) {
const { users, fetchUser } = useUserStore();
useEffect(() => {
fetchUser(id);
}, [id, fetchUser]);
return <img src={users[id]?.avatar} />;
}方案四:工业标准请求库(强烈推荐)
现代 React 开发中,处理缓存的最佳实践是使用 TanStack Query (React Query) 或 SWR。它们将异步逻辑与状态管理彻底分离。
1. TanStack Query (旗舰方案)
tsx
import { useQuery } from '@tanstack/react-query';
const useUser = (id) =>
useQuery({
queryKey: ['user', id],
queryFn: () => fetchUser(id),
staleTime: 1000 * 60 * 5, // 5 分钟内数据被视为“新鲜”,不触发重复请求
});核心优势:
- 自动去重:同时发起的相同
queryKey请求会被合并为一个。 - 失效重连:当窗口重新聚焦或网络恢复时,自动更新数据。
- 内存管理:自动清理长时间不使用的缓存数据。
- 开发工具:强大的专用 Devtools 调试工具。
2. SWR (轻量快捷)
tsx
import useSWR from 'swr';
const useUser = (id) => useSWR(`/api/user/${id}`, fetcher);特点:
- Stale-While-Revalidate:先从缓存展示旧数据,同时在后台发送请求获取最新数据。
- 体积小:非常轻量,适合小型项目。
总结:如何选择?
| 场景 | 推荐方案 |
|---|---|
| 单组件极简场景 | 方案一 (State) |
| 中小型项目 / 逻辑简单 | 方案三 (Zustand) 或 SWR |
| 大型复杂应用 / 强交互 | React Query (推荐) |
| 静态文档流 / 简单共享 | 方案二 (Global Map) |
TIP
结论:如果你的项目有大量的异步数据交互,直接使用 React Query。它能帮你解决 90% 的数据同步和缓存痛点。
