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

React中fetch调用后useEffect清理函数的实现方法

解决React中useEffect内fetch请求的清理问题

你遇到的核心问题是:组件卸载后,未完成的fetch请求仍会继续执行,最终调用setImageContainer时会触发已卸载组件的状态更新警告,同时未完成的请求也会浪费资源。用浏览器原生的AbortController就能完美解决这个问题,它可以主动终止fetch请求。

具体实现步骤:

  • 创建AbortController实例,它会生成一个signal信号,用来关联所有需要终止的请求
  • 给每个fetch请求添加signal参数,绑定到这个controller的signal上
  • 在useEffect的返回清理函数中调用controller.abort(),终止所有未完成的请求
  • 捕获请求被中止的错误,避免控制台出现不必要的报错

修改后的代码:

const [imageContainer, setImageContainer] = useState([]);
const navigate = useNavigate();

useEffect(() => {
  // 创建AbortController实例
  const abortController = new AbortController();
  const { signal } = abortController;

  Promise.all([
    fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()),
    fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()),
    fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()),
    fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()),
    fetch("https://www.themealdb.com/api/json/v1/1/random.php", { signal }).then(response => response.json()),
  ])
    .then(response => {
      setImageContainer(response.map(recipe => recipe.meals[0]));
    })
    .catch(error => {
      // 忽略请求被中止的错误,避免控制台报错
      if (error.name !== "AbortError") {
        console.error("请求出错:", error);
      }
    });

  // 清理函数:组件卸载时终止所有未完成的请求
  return () => abortController.abort();
}, []);

关键说明:

  • abortController.abort()会触发所有关联该signal的fetch请求立即中止,后续的.then回调不会再执行,自然避免了组件卸载后调用setImageContainer的问题
  • 捕获AbortError是因为中止请求会抛出这个错误,它不属于业务错误,所以只在非中止错误时打印日志
  • 你的useEffect依赖项是空数组,清理函数只会在组件卸载时执行,完全匹配你的场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 18:22:19