React Native中useEffect调用API触发未挂载组件状态更新警告的解决方法
报错根源
切换页面导致HomeScreen组件被卸载时,未完成的异步API请求、持续运行的时长统计定时器仍在后台执行,执行完成后触发setState修改已卸载组件的状态,就会弹出「Can't perform a React state update on an unmounted component」的警告。
具体修复步骤
1. 增加组件挂载状态标记
用useRef存储组件的挂载状态(不会触发重渲染,适合存这类逻辑判断标记),所有状态更新操作执行前先判断组件是否还处于挂载状态,未挂载则直接跳过状态修改。
// 标记组件是否仍处于挂载状态 const isMountedRef = useRef(true);
2. 重构定时器存储逻辑
原代码把定时器ID存在state里的写法存在时序bug:setDeleteExecutionCounting是异步执行的,后续引用时很容易拿到旧的定时器值,导致定时器无法被正常清理。将定时器ID直接存在ref中,实现统一管理、统一清理。
// 存储正在运行的定时器ID const timerRef = useRef(null);
3. 增加卸载清理逻辑
编写仅在组件挂载/卸载时执行的副作用,组件卸载时完成两件核心清理工作:将挂载标记设为false、清除所有正在运行的定时器,彻底切断后台触发状态更新的源头。
useEffect(() => { isMountedRef.current = true; return () => { // 组件卸载时执行清理 isMountedRef.current = false; if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; } } }, []);
4. 改造loadData的状态更新逻辑
所有异步回调内的状态更新,先判断组件是否还挂载,未挂载则直接返回不执行setState;同时替换原代码的串行then链,用finally做统一的收尾清理,避免清理逻辑漏执行。
const loadData = useCallback(() => { // 先清理上一次未结束的定时器,避免多个定时器并行运行 if (timerRef.current) { clearInterval(timerRef.current); } // 启动请求时长统计定时器 timerRef.current = setInterval(() => { // 状态更新前先判断挂载状态 if (isMountedRef.current) { setExecutionDuration(prev => prev + 1); } }, 2000); setError(false); setLoading(true); getRowsFromDb(Id) .then(response => { if (!isMountedRef.current) return; if (response.status === 204) { setData({ rows: [], count: 0 }); } else { setData(response.data); } }) .catch(err => { if (!isMountedRef.current) return; setError(true); }) .finally(() => { if (!isMountedRef.current) return; // 收尾清理定时器 if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; } setExecutionDuration(0); setLoading(false); }); }, [Id]);
可选优化项
- 原代码同时在useEffect内直接调用
loadData、又绑定了屏幕focus事件,组件首次挂载时会触发两次重复的API请求,可以去掉那个直接调用loadData的useEffect,让所有刷新逻辑统一走focus事件触发,减少无效请求。 - 原代码在loading渲染判断里直接读取
executionDurationRef.current的值,ref变化不会触发重渲染,会导致超时提示不能及时更新,直接读取state里的executionDuration值即可。 - 如果用Axios发请求,可配合
AbortController在组件卸载时直接取消未完成的请求,从源头减少无效网络请求,降低资源消耗。
内容的提问来源于stack exchange,提问作者Christian Cascone
相关产品推荐
相关产品推荐

