Skip to content

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% 的数据同步和缓存痛点。