React Hook中如何解决useEffect触发的内存泄漏警告问题
React useEffect异步请求内存泄漏警告修复方案
问题原因
你遇到的警告触发逻辑非常清晰:点击登出后history.push('/signin')会卸载当前页面组件,但你在useEffect中触发的axios异步请求还在pending状态,等请求成功返回执行setUserData更新组件状态时,目标组件已经被销毁,React就会抛出该警告,未被处理的异步任务也会造成内存泄漏风险。
修复方案
方案1:使用AbortController取消未完成请求(推荐)
Axios从v0.22.0开始支持用AbortController取消请求,直接从根源终止未完成的异步任务,避免后续无效的状态更新,同时节省网络资源。
修改后的代码如下:
useEffect(() => { // 实例化中断控制器 const controller = new AbortController(); const getUserData = () => { axios.get(`${API_URL}`, { // 绑定中断信号到当前请求 signal: controller.signal }).then((res) => { if (res.data) { setUserData(res.data); } }).catch(err => { // 忽略请求主动取消的错误 if (axios.isCancel(err)) return; // 其他业务错误正常处理 console.error('用户数据请求失败', err); }) }; getUserData(); // 组件卸载时执行的清理函数 return () => { controller.abort(); }; }, []); const logout = () => { signout(() => { history.push('/signin'); }); }; return ( <div> <button onClick={() => logout()}>Sign out </button> </div> );
方案2:挂载状态标记(兼容旧版本Axios)
如果你使用的Axios版本较低不支持AbortController,可以用ref标记组件挂载状态,请求返回后只有组件还处于挂载状态才更新状态。该方案不会终止请求,仅跳过无效的状态更新操作。
修改后的代码如下:
useEffect(() => { // 标记组件是否处于挂载状态 let isMounted = true; const getUserData = () => { axios.get(`${API_URL}`).then((res) => { if (isMounted && res.data) { setUserData(res.data); } }); }; getUserData(); return () => { // 组件卸载时修改标记 isMounted = false; }; }, []);
内容的提问来源于stack exchange,提问作者Gabriel Udo
相关产品推荐
相关产品推荐

