You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为React组件的请求添加缓存,避免重复请求相同参数的资源

实现方案

核心思路是额外维护一个缓存结构存储已经请求过的index和对应的数据,每次请求前先检查缓存,命中则直接使用缓存数据,未命中再发起请求,请求成功后将结果写入缓存。

方案1:组件实例独享缓存

仅当前组件实例可以复用缓存,适合不需要跨组件共享数据的场景,用useRef存储缓存对象(useRef的内容不会随组件重渲染重置)。

改造后代码:

import { useState, useEffect, useRef } from 'react';

function MyComponent({ index }) {
  const [data, setData] = useState('');
  // 用Map作为缓存结构,key为index,value为对应请求结果
  const requestCache = useRef(new Map());

  useEffect(() => {
    // 缓存命中直接赋值,跳过请求
    if (requestCache.current.has(index)) {
      setData(requestCache.current.get(index));
      return;
    }

    // 标记位,避免竞态问题:index快速切换时旧请求返回后覆盖新数据
    let isActive = true;
    (async function() {
      const result = await fetchData(index);
      if (isActive) {
        setData(result);
        // 请求成功后写入缓存
        requestCache.current.set(index, result);
      }
    })();

    // 组件卸载/ index变化时触发清理,标记当前请求无效
    return () => {
      isActive = false;
    };
  }, [index]);

  return <h1>{data}</h1>;
}

方案2:多实例全局共享缓存

如果有多个MyComponent实例需要复用同一份缓存数据,可以把缓存对象提到组件外部,所有实例都读写同一个缓存结构。

改造后代码:

import { useState, useEffect } from 'react';

// 全局缓存,所有MyComponent实例共享
const GLOBAL_REQUEST_CACHE = new Map();

function MyComponent({ index }) {
  const [data, setData] = useState('');

  useEffect(() => {
    if (GLOBAL_REQUEST_CACHE.has(index)) {
      setData(GLOBAL_REQUEST_CACHE.get(index));
      return;
    }

    let isActive = true;
    (async function() {
      const result = await fetchData(index);
      if (isActive) {
        setData(result);
        GLOBAL_REQUEST_CACHE.set(index, result);
      }
    })();

    return () => {
      isActive = false;
    };
  }, [index]);

  return <h1>{data}</h1>;
}

扩展优化点

  • 可以在存储缓存时同时记录时间戳,查询缓存时判断是否超过有效期,实现自动过期清理
  • 如果缓存key是复杂对象,可以序列化后作为Map的key
  • 缓存条目较多时可以加入LRU淘汰逻辑,避免内存占用过高

内容的提问来源于stack exchange,提问作者Vic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 05:18:02