在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
相关产品推荐
相关产品推荐

