React Native从AsyncStorage取两值作为Fetch参数时遇无限更新报错
解决React中「Maximum update depth exceeded」无限循环错误
错误原因分析
你遇到的无限循环问题,核心在于第二个useEffect的依赖数组包含了data:
- 当
city或code更新时,触发effect执行fetch请求 - 请求完成后调用
setData(data)更新状态,data的变化会再次触发这个effect - 如果接口返回的
data是空数组(或者data.length始终为0),就会重复进入if (data.length == 0)的判断,无限发起请求
修复方案及优化代码
下面是调整后的代码,从根源解决循环问题,同时优化异步逻辑:
import { useState, useEffect } from 'react'; import AsyncStorage from '@react-native-async-storage/async-storage'; const YourComponent = () => { const [data, setData] = useState([]); const [code, setCode] = useState(''); const [city, setCity] = useState(''); const [loading, setLoading] = useState(true); // 新增标记:记录是否已发起过请求,避免重复触发 const [isFetched, setIsFetched] = useState(false); // 从AsyncStorage获取城市和编码 useEffect(() => { const fetchStorageData = async () => { try { // 用Promise.all同时获取两个值,提升异步效率 const [cityVal, codeVal] = await Promise.all([ AsyncStorage.getItem('city'), AsyncStorage.getItem('code') ]); setCity(cityVal || ''); setCode(codeVal || ''); } catch (error) { console.error('获取存储数据失败:', error); setLoading(false); } }; fetchStorageData(); }, []); // 根据城市和编码发起接口请求 useEffect(() => { // 仅当城市、编码都存在,且未发起过请求、处于加载状态时才执行 if (city && code && !isFetched && loading) { const fetchApiData = async () => { try { const response = await fetch(`apiurlhere/${city}/${code}`); const resData = await response.json(); setData(resData); } catch (error) { console.error('接口请求失败:', error); } finally { // 无论请求成败,都标记为已请求并结束加载 setLoading(false); setIsFetched(true); } }; fetchApiData(); } else if (!city || !code) { // 若缺少必要参数,直接结束加载 setLoading(false); } }, [city, code, loading, isFetched]); // 后续渲染逻辑... return ( // 你的组件内容 ); }; export default YourComponent;
关键修改说明
- 移除
data作为依赖:避免setData触发的状态更新重复调用effect - 新增
isFetched标记:确保接口仅请求一次,彻底杜绝循环 - 参数有效性判断:只有当
city和code都不为空时才发起请求,避免无效URL - 异步逻辑优化:用
Promise.all同时获取两个存储值,减少异步等待时间 - 状态兜底处理:无论请求成败都更新
loading和isFetched,避免组件一直处于加载状态
内容的提问来源于stack exchange,提问作者Mathunya
相关产品推荐
相关产品推荐

