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

在useEffect中使用history.push导致React内存泄漏问题求助

解决React组件卸载后异步请求更新state的内存泄漏警告

问题根源

调用history.push('/firstpage')后,Home组件会立即被卸载,但此时异步请求仍在后台执行。当请求完成后,代码尝试更新已卸载组件的state,就会触发"Can't perform a React state update on an unmounted component"警告。

解决方案

1. 使用AbortController终止未完成的请求(推荐)

这种方法能直接终止后台的异步请求,从根源避免后续的state更新操作,同时节省网络资源。

import { useEffect } from 'react';
import { useHistory } from 'react-router-dom';

function Home() {
  const history = useHistory();

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

    const fetchTasks = async () => {
      try {
        // 请求时传入signal,用于后续终止请求
        const res = await fetch('/api/tasks', { signal });
        const { tasks } = await res.json();

        if (tasks.length < 1) {
          history.push('/firstpage', { yourStateKey: 'stateValue' });
        } else {
          // 正常更新组件state
          // setTasks(tasks);
        }
      } catch (err) {
        // 忽略请求被终止的错误
        if (err.name !== 'AbortError') {
          console.error('获取任务失败:', err);
        }
      }
    };

    fetchTasks();

    // 组件卸载时终止请求
    return () => abortController.abort();
  }, [history]);

  return <div>Home Page</div>;
}

export default Home;

2. 使用挂载状态标志位跳过state更新

如果你的异步请求无法通过AbortController终止(比如依赖不支持该API的第三方库),可以用一个标志位跟踪组件是否仍挂载,请求完成后先判断标志位再执行state更新。

import { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';

function Home() {
  const history = useHistory();
  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    let isMounted = true;

    const fetchTasks = async () => {
      try {
        const res = await fetch('/api/tasks');
        const { tasks } = await res.json();

        // 组件已卸载,直接返回,不执行后续操作
        if (!isMounted) return;

        if (tasks.length < 1) {
          history.push('/firstpage', { yourStateKey: 'stateValue' });
        } else {
          setTasks(tasks);
        }
      } catch (err) {
        console.error('获取任务失败:', err);
      }
    };

    fetchTasks();

    // 组件卸载时标记为已卸载
    return () => {
      isMounted = false;
    };
  }, [history]);

  return <div>Home Page</div>;
}

export default Home;

注意事项

  • 优先选择AbortController方案,它能真正终止请求,减少不必要的网络开销和资源占用。
  • 如果使用axios等库,它们也支持基于AbortController的请求取消(axios v0.22.0+支持),用法类似。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:01:38