使用自定义useFetch请求数据时触发组件卸载后无法更新React state警告如何修复
修复方案
问题根因
这个警告是因为请求未完成时使用该Hook的组件已经卸载,请求返回后仍尝试执行状态更新操作,属于典型的异步任务未清理导致的内存泄漏问题。
修复方法(推荐:直接取消未完成请求)
利用Axios支持的AbortController接口,在useEffect的清理函数中主动取消未完成的请求,从根源避免后续的状态更新操作,同时还能节省无用的网络开销。
修复后的完整代码如下:
import { useState, useEffect } from "react"; import axios from "axios"; const useFetch = (url) => { const [data, setData] = useState(null); const [error, setError] = useState(null); useEffect(() => { // 实例化AbortController用于控制请求取消 const controller = new AbortController(); axios .get(url, { // 绑定signal到当前请求 signal: controller.signal }) .then((response) => { setData(response.data); }) .catch((err) => { // 排除主动取消请求导致的错误,不需要处理 if (!axios.isCancel(err)) { setError(err); } }); // useEffect清理函数,组件卸载时执行 return () => { // 主动取消未完成的请求 controller.abort(); } }, [url]); return { data, error }; }; export default useFetch;
替代方案:挂载状态标记
如果你不需要主动取消请求,只需要避免给卸载的组件更新状态,可以通过挂载标记判断是否执行状态更新:
import { useState, useEffect } from "react"; import axios from "axios"; const useFetch = (url) => { const [data, setData] = useState(null); const [error, setError] = useState(null); useEffect(() => { // 标记组件是否处于挂载状态 let isMounted = true; axios .get(url) .then((response) => { // 仅组件挂载时才更新状态 if (isMounted) { setData(response.data); } }) .catch((err) => { if (isMounted) { setError(err); } }); return () => { // 组件卸载时修改标记 isMounted = false; } }, [url]); return { data, error }; }; export default useFetch;
注意:该方案仅规避了状态更新的警告,没有取消未完成的请求,仍会占用网络资源,优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者ahmedskulj10
相关产品推荐
相关产品推荐

