Next.js调用OpenWeather API后遇push属性未定义错误的解决方法
解决「TypeError: Can't read properties of undefined (reading 'push')」错误
错误原因
- 初始状态边界问题:组件初始化时
fiveDayForecast是空数组,第一次执行状态更新时,updatedForecast.length - 1等于-1,访问updatedForecast[-1]得到undefined,调用push方法触发错误。 - 渲染阶段重复触发状态更新:在组件渲染逻辑中直接遍历
list并调用setFiveDayForecast,导致组件每次渲染都重复执行这段代码,不断触发状态更新和重新渲染,逻辑混乱且效率低下。 - 缺少空值判断:未处理API数据未加载完成(
data或list为undefined)的情况,直接解构和访问属性会引发额外错误。
解决方案
- 添加空值与加载状态Civil处 �PU/ OccupOff园眉�ftpers 处理:在使用
data前先判断其是否存在,避免访问undefined的属性。 - 用
useMemo预处理数据:将五天预报的分组逻辑改为纯数据转换,通过useMemo缓存计算结果,仅在data变化时重新计算,避免频繁的状态更新。 - 优化分组逻辑:使用for循环替代forEach,先初始化第一组数据,再遍历剩余元素完成分组,避免初始空数组导致的边界错误。
修改后代码
"use client"; import React, { useMemo } from "react"; const ForecastDay = ({ data }) => { // 处理数据未加载或为空的情况 if (!data?.list || data.list.length === 0) { return <div>加载中...</div>; } const fiveDayForecast = useMemo(() => { const { list } = data; const groupedForecast = []; // 初始化第一组数据 let currentDate = list[0].dt_txt.split(" ")[0]; let currentGroup = [list[0]]; // 从第二个元素开始遍历分组 for (let i = 1; i < list.length; i++) { const forecast = list[i]; const forecastDate = forecast.dt_txt.split(" ")[0]; if (forecastDate !== currentDate) { // 将当前组存入结果,切换新日期并初始化新组 groupedForecast.push(currentGroup); currentDate = forecastDate; currentGroup = [forecast]; } else { // 同日期的预报加入当前组 currentGroup.push(forecast); } } // 加入最后一组数据 groupedForecast.push(currentGroup); return groupedForecast; }, [data]); // 仅当data变化时重新计算 return ( <div> {fiveDayForecast.map((day, index) => ( <div key={index}> <h2>Günün Tarihi: {day[0].dt_txt.split(" ")[0]}</h2> {day.map((forecast) => ( <div key={forecast.dt}> <p>Saat: {forecast.dt_txt.split(" ")[1]}</p> <p>Sıcaklık: {forecast.main.temp}°F</p> </div> ))} </div> ))} </div> ); };
关键修改说明
- 空值判断:通过
!data?.list || data.list.length === 0拦截未加载完成的状态,避免访问无效数据。 - 状态逻辑替换:移除了
useState和循环内的setState,改用useMemo直接计算分组结果,符合React纯数据转换的最佳实践,避免了频繁渲染和状态更新的问题。 - 分组逻辑优化:先初始化第一组数据,再从第二个元素开始遍历,彻底解决了初始空数组导致的
push错误。
内容的提问来源于stack exchange,提问作者Ömer Düzgün
相关产品推荐
相关产品推荐

