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

如何解决React报错:无法在已卸载组件上执行状态更新

解决React组件卸载后异步请求更新状态的警告问题

当组件发起异步请求后,在请求完成前切换页面导致组件卸载,此时请求响应回来后调用setState就会触发Warning: Can't perform a React state update on an unmounted component警告——因为组件实例已经不存在了。AbortController完全适用于这个场景,你之前没成功应该是用法不对,下面是具体的解决步骤:

1. 修改Axios工具函数,支持传入终止信号

首先需要让你的apiGetCall函数接受AbortController的signal参数,这样才能在组件卸载时取消请求:

// axios utils
export const apiGetCall = (url, signal) => axiosInstance.get(url, { signal });

2. 在组件的useEffect中使用AbortController并添加挂载状态检查

在发起请求的useEffect里,创建AbortController实例,把signal传给请求,同时设置一个isMounted标志位作为双重保险,组件卸载时更新这个标志并终止请求:

useEffect(() => {
  const abortController = new AbortController();
  let isMounted = true; // 标记组件是否仍挂载

  const fetchData = async () => {
    try {
      // 将signal传入请求
      const response = await apiGetCall("/departments", abortController.signal);
      const departmentsData = response.data.departments;

      // 只有组件仍挂载时才更新状态
      if (isMounted) {
        setDepartmentData(departmentsData);
        setPieChartOptions({
          // 部门数据配置
        });
      }
    } catch (err) {
      // 忽略请求被主动取消的错误,只处理其他异常
      if (!axios.isCancel(err)) {
        console.log(err);
      }
    }
  };

  fetchData();

  // 组件卸载时执行清理:更新挂载状态+终止请求
  return () => {
    isMounted = false;
    abortController.abort();
  };
}, []);

3. 对三个请求逐一处理

你的组件有三个独立请求,需要给每个请求都应用上述逻辑(可以复用同一个AbortController来终止所有请求,也可以每个请求单独创建,效果一致)。比如用同一个控制器并行处理三个请求:

useEffect(() => {
  const abortController = new AbortController();
  let isMounted = true;

  const fetchDepartments = async () => {
    try {
      const response = await apiGetCall("/departments", abortController.signal);
      if (isMounted) {
        // 更新部门相关状态
      }
    } catch (err) {
      if (!axios.isCancel(err)) console.log(err);
    }
  };

  const fetchChart2Data = async () => {
    try {
      const response = await apiGetCall("/chart2-data", abortController.signal);
      if (isMounted) {
        // 更新图表2相关状态
      }
    } catch (err) {
      if (!axios.isCancel(err)) console.log(err);
    }
  };

  const fetchChart3Data = async () => {
    try {
      const response = await apiGetCall("/chart3-data", abortController.signal);
      if (isMounted) {
        // 更新图表3相关状态
      }
    } catch (err) {
      if (!axios.isCancel(err)) console.log(err);
    }
  };

  // 并行发起三个请求
  Promise.all([fetchDepartments(), fetchChart2Data(), fetchChart3Data()]);

  return () => {
    isMounted = false;
    abortController.abort();
  };
}, []);

这样修改后,当你切换页面卸载组件时,会立即终止所有未完成的请求,同时即使请求已经进入响应阶段,也会通过isMounted标志跳过状态更新,彻底解决这个警告问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 04:52:54