如何修复React useEffect报错“Warning: Can't perform a React state update on an unmounted component”
问题原因与解决方法
你遇到的是React中典型的「卸载组件更新状态」警告,触发逻辑是:
- 管理员账号进入Dashboard组件后,useEffect触发路由跳转,此时Dashboard及其下的所有Row子组件已经开始挂载,每个Row组件内部的useEffect已经执行发起了视频接口请求
- 路由跳转后Dashboard组件直接被卸载,所有Row子组件也随之卸载
- 等异步接口请求返回执行
setVideos时,目标组件已经不存在,就抛出了useEffect相关的警告
1. 优先优化Dashboard跳转逻辑(根因修复)
直接在Dashboard组件中提前判断管理员身份,符合条件直接返回null不渲染任何子组件,同时补全useEffect的依赖数组避免ESLint警告:
export default function Dashboard() { const user = useSelector((state) => state.user); const role = user.user_info?.roles; // 加可选链避免空值报错 const history = useHistory(); useEffect(() => { if (role === "admin") { history.push("/admin-dashboard"); } }, [role, history]); // 补全依赖数组 // 管理员直接返回null,不渲染任何子组件,避免子组件触发无效请求 if (role === "admin") return null; return ( <React.Fragment> <Banner /> <Row1 /> <Row2 /> <Row3 /> <Row4 /> <Row5 /> <Row6 /> </React.Fragment> ); }
2. 子组件添加卸载状态判断(兜底方案)
如果后续还有其他场景需要处理组件卸载时的异步请求,可以给每个Row组件的useEffect添加挂载标记,组件卸载后就不再更新状态:
useEffect(() => { let isMounted = true; const getData = async () => { const data = await getAllVideosTopRated(); // 只有组件还处于挂载状态时才更新state if (isMounted) { setVideos(data); } }; getData(); // 组件卸载时更新标记位 return () => { isMounted = false; }; }, []);
3. 修复接口请求的潜在问题
你当前的接口请求代码使用了全局变量data存储返回结果,并发请求时会出现变量覆盖的问题,建议调整为直接返回请求结果:
export const getAllVideos = async () => { try { const res = await axios.post(`${apis.all}`); return res.data; } catch (err) { console.log(err); return null; } };
额外优化建议
可以把角色判断逻辑提到路由守卫层,在进入页面前就完成角色校验和跳转,完全不需要渲染Dashboard组件,性能和逻辑合理性都会更好。
内容的提问来源于stack exchange,提问作者chaitu605
相关产品推荐
相关产品推荐

