useEffect清理函数解决组件卸载后状态更新报错的方案咨询
现有实现存在的问题
- 逻辑错误:取消请求后未区分错误类型,直接读取
error.response.status会触发异常。axios主动取消请求时抛出的错误不存在response属性,直接访问status会报Cannot read properties of undefined错误。 - 冗余逻辑:服务层
ProductService.getProducts中的try/catch完全多余,没有做任何额外处理只是原封不动抛出错误,可以直接删除简化代码。
可优化的点
- 新增取消错误过滤:在请求catch块中通过
axios.isCancel()方法过滤主动取消的请求,不做错误日志打印,同时对error.response增加可选链判断,避免读取不存在的属性报错。 - 增加卸载状态双重校验:除了取消请求外,新增组件是否卸载的标记位,即使请求没有被成功取消,也不会对已卸载组件更新state,兼容后续换用fetch等其他请求库的场景。
- 替换废弃的CancelToken:axios v0.22.0及以上版本已经将CancelToken标记为弃用,推荐使用符合Web标准的
AbortController实现请求取消,通用性更强。
优化后代码示例
组件层代码
const [products, setProducts] = useState([]); useEffect(() => { const controller = new AbortController(); let isMounted = true; const fetchProducts = async () => { try { const data = await ProductService.getProducts(controller.signal); // 更新state前先判断组件是否仍挂载 if (isMounted) { setProducts(data); } } catch (error) { // 跳过主动取消的请求错误 if (axios.isCancel(error)) return; // 可选链避免读取不存在的属性报错 console.log(error.message, error.response?.status); } }; fetchProducts(); return () => { isMounted = false; controller.abort(); }; }, []);
服务层代码(简化后)
const ProductService = { getProducts: function (signal) { return axios.get(myURL, { signal }).then(res => res.data); } };
内容的提问来源于stack exchange,提问作者Nasir
相关产品推荐
相关产品推荐

