如何解决useEffect中使用redux时出现的内存泄漏问题
问题原因
现有清理逻辑失效的核心问题是判断clean标记的时机错误:你仅在调用异步加载函数前判断标记,此时组件刚完成挂载,标记必然为true,无法拦截后续异步操作结束后的状态更新。当你通过NavLink跳转页面后组件已卸载,但dispatch(loadlist())的异步逻辑仍会继续执行,执行完成后调用setIsShow(true)更新已卸载组件的状态,就会触发内存泄漏警告。
修复方案
最小改动修复
仅调整清理标记的判断位置,放到异步操作结束后、状态更新前即可:
function List() { const [isShow, setIsShow] = useState(false); const dispatch = useDispatch(); const list = useSelector((state) => state.list); useEffect(() => { let unmounted = false; async function load() { await dispatch(loadlist()); // 异步执行完成后先校验组件是否卸载,再更新状态 if (!unmounted) { setIsShow(true); } } setIsShow(false); load(); return () => { unmounted = true; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return isShow ? <Table data={list} /> : <Loading />; }
进阶优化(适配Redux Toolkit异步场景)
如果你的loadlist是通过createAsyncThunk创建的异步Action,还可以通过AbortController直接终止异步请求,从根源避免后续多余的逻辑执行:
useEffect(() => { const controller = new AbortController(); async function load() { try { // 向异步Action传递取消信号 await dispatch(loadlist({ signal: controller.signal })).unwrap(); setIsShow(true); } catch (err) { // 忽略请求取消的异常 if (err.name !== 'AbortError') { console.error('列表加载失败', err); } } } setIsShow(false); load(); return () => { controller.abort(); // 组件卸载时终止异步请求 }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []);
你用useState代替useDispatch时警告消失,本质是对应异步逻辑的状态更新时机刚好被你原有逻辑覆盖,并不是useDispatch本身存在问题。
内容的提问来源于stack exchange,提问作者extradeck
相关产品推荐
相关产品推荐

