React调用moves.monz[0]报Cannot read properties of undefined错误排查
问题根因
- React的状态更新是异步批量执行的,你调用
setMoves(json)之后,当前getMoves函数作用域里的moves还是更新前的旧值,不会立刻变成你传入的接口返回数据。
你看到控制台打印moves、moves.charizard有值,是浏览器控制台的惰性求值特性:打印对象/数组时控制台存储的是引用,等你手动展开查看的时候,状态已经更新完成,所以显示的是最新值。但实际执行console.log这行代码的时刻,moves还是初始的空数组,没有monz属性,所以moves.monz为undefined,访问[0]就会抛出错误。 moves状态的初始值类型错误:你接口返回的是包含charizard、monz属性的对象,但初始值设置了空数组[],数组本身也不可能有monz这个自定义属性。
修复方案
- 在
getMoves函数里要访问刚拿到的接口数据,直接用请求得到的json变量即可,不要用还没更新的状态值:
const getMoves = async () => { const req = await fetch(`/api/move-data/${league}`); const json = await req.json(); setMoves(json); // 直接用json访问最新的接口数据 console.log(json); console.log(json.charizard); console.log(monz[0]); console.log(json.monz[0]); // 此处运行正常 };
- 修正
moves状态的初始值,和接口返回的类型对齐:
// 初始值从空数组改为空对象 const [moves, setMoves] = useState({});
- 渲染时访问嵌套属性要加可选链做空值判断,避免状态还没更新时的报错:
{moves?.monz?.[0]?.Name}
- 额外优化:你当前的
monz是普通变量,在渲染的map逻辑里直接push会导致每次组件重渲染都重复推入数据,建议把monz的计算逻辑抽出来,不要在渲染过程中修改外部变量:
// 直接计算得到monz,不要在map里执行push操作 const monz = teams.slice(1).flatMap(team => Array.isArray(team) ? team.slice(1).map(p => p.pokemon.toLowerCase()) : [] )
内容的提问来源于stack exchange,提问作者Liiaam93
相关产品推荐
相关产品推荐

