解决useEffect+axios触发Maximum Update Depth Exceeded错误问题
解决React useEffect无限更新(Maximum Update Depth Exceeded)问题
错误信息
Maximum Update Depth Exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render
问题场景
使用useEffect请求汇率接口时触发上述错误,模拟器出现白屏;改用本地示例数据直接设置状态时,代码可正常运行。接口密钥已替换为真实值,链接在浏览器测试可用(示例数据取自该接口)。
原始代码
const [data, setData] = useState() const [rates, setRates] = useState() const [baseCurrencies, setBases] = useState(); const [resultCurrencies, setResult] = useState(); useEffect(() => { const fetchData = async () => { const response = await axios.get('https://api.apilayer.com/exchangerates_data/latest?apikey={KEY IS HERE}&base=EUR') const data = response.data if(data){ setData(data) setRates(data.rates) setBases(getSymbols(data)) setResult(getSymbols(data)) } } fetchData() }, [])
解决方案
1. 稳定getSymbols函数
错误核心原因大概率是getSymbols每次调用返回新的引用(如数组/对象),或函数本身在组件每次渲染时被重新创建,导致状态更新后触发无限重渲染。
- 若
getSymbols不依赖组件内部状态/ props,直接移到组件外部:
// 组件外部定义,确保引用稳定 const getSymbols = (data) => { if (!data?.rates) return []; return Object.keys(data.rates); };
- 若必须在组件内部定义,用
useCallback缓存函数引用:
import { useCallback } from 'react'; // 组件内部 const getSymbols = useCallback((data) => { if (!data?.rates) return []; return Object.keys(data.rates); }, []); // 空依赖数组保证函数引用稳定
2. 优化状态初始化与更新
给状态设置合理初始值,避免undefined引发的意外渲染;同时减少重复计算:
// 给状态设置初始值 const [data, setData] = useState(null); const [rates, setRates] = useState({}); const [baseCurrencies, setBases] = useState([]); const [resultCurrencies, setResult] = useState([]); useEffect(() => { const fetchData = async () => { try { const response = await axios.get('https://api.apilayer.com/exchangerates_data/latest?apikey={KEY IS HERE}&base=EUR'); const fetchedData = response.data; if (fetchedData) { setData(fetchedData); setRates(fetchedData.rates); // 只计算一次货币符号,避免重复调用getSymbols const symbols = getSymbols(fetchedData); setBases(symbols); setResult(symbols); } } catch (err) { console.error('汇率数据请求失败:', err); // 可添加错误提示状态,避免白屏 } }; fetchData(); }, []); // 若getSymbols在组件内且用了useCallback,可添加getSymbols到依赖数组
3. 解决白屏问题
在组件渲染时增加加载/空状态判断,防止数据未返回时因访问data属性报错:
return ( <div> {data ? ( // 渲染正常内容 <div>基础货币:{baseCurrencies.join(', ')}</div> ) : ( <div>加载中...</div> )} </div> );
内容的提问来源于stack exchange,提问作者Andrea Borg
相关产品推荐
相关产品推荐

