React useEffect持续执行致API无限调用问题求助
解决React useEffect无限调用API的问题
问题根源
你遇到的无限循环,核心原因有两个:
- 错误使用
useMemo缓存函数:useMemo的作用是缓存计算值,缓存函数应该用useCallback;且你的useMemo未指定依赖数组,导致每次组件渲染都会重新创建fetchData函数。 useEffect依赖fetchData:每次渲染生成新的fetchData引用,会触发useEffect执行,调用API后修改状态又触发渲染,形成循环。- 代码语法错误:
axios.get的参数缺少逗号,会导致执行报错。
解决方案
方案一:用useCallback缓存函数
将useMemo替换为useCallback,并添加正确的依赖数组,确保函数引用仅在依赖变化时更新:
// 保存数据的useState不变 const [loadData, setLoadData] = useState([]); // 用useCallback缓存异步函数 const fetchData = useCallback(async () => { try { // 修正axios参数的逗号问题 const responseData = await axios.get(baseUrl, { withCredentials: true }); // responseData.data是同步值,不需要await const details = responseData.data; setapiLoading(false); if (details.length === 0) { setLoadData(null); } else { setLoadData(details); } } catch (error) { toast.error(`${error}: Please try again`, { position: toast.POSITION.TOP_CENTER }); } }, [baseUrl, setapiLoading, setLoadData, toast]); // 添函数内部用到的所有外部依赖 // useEffect依赖缓存后的fetchData useEffect(() => { fetchData(); }, [fetchData]);
方案二:将函数写在useEffect内部(仅挂载时执行一次)
如果你的需求是仅在组件挂载时调用一次API,可以直接把fetchData定义在useEffect内部,省略useCallback:
const [loadData, setLoadData] = useState([]); useEffect(() => { const fetchData = async () => { try { const responseData = await axios.get(baseUrl, { withCredentials: true }); const details = responseData.data; setapiLoading(false); if (details.length === 0) { setLoadData(null); } else { setLoadData(details); } } catch (error) { toast.error(`${error}: Please try again`, { position: toast.POSITION.TOP_CENTER }); } }; fetchData(); }, [baseUrl, setapiLoading, setLoadData, toast]); // 仅依赖内部用到的变量
关键说明
useCallback专门用于缓存函数引用,只有当依赖数组中的变量变化时,才会生成新的函数。- 依赖数组必须包含函数内部用到的所有外部变量/状态/函数,否则会出现闭包问题,获取到旧值。
- 修正
axios.get的参数逗号,确保代码能正常执行。
内容的提问来源于stack exchange,提问作者K.Kishore
相关产品推荐
相关产品推荐

