React中解析Axios Get请求天气API响应报错求助
问题解决:React解析天气API响应的两个常见错误
错误原因分析
TypeError: Cannot read properties of undefined (reading 'temp')
- 你的初始状态
res设为了空数组[],但API返回的是对象。组件挂载时,res是空数组,没有main属性,直接访问res.main.temp就会报错。 - 现有判断
if (!res)无效,因为空数组在JS中是真值,不会触发返回null的逻辑。
- 你的初始状态
Objects are not valid as a React child
- React无法直接渲染对象,
res.main是包含多个字段的对象,直接放到JSX里会触发这个错误,必须渲染具体的属性值。
- React无法直接渲染对象,
解决方案
步骤1:修正初始状态
将res的初始值设为null(匹配API返回的对象类型,且是假值,方便条件判断):
const [res, setRes] = React.useState(null)
步骤2:添加加载状态判断
在数据加载完成前,渲染加载提示或者空内容:
if (!res) return <div className="Resort">Loading weather data...</div>;
步骤3:安全访问嵌套属性
使用可选链操作符?.避免访问未定义属性时报错,同时逐个渲染需要的字段:
<h3>当前温度: {res.main.temp} °F</h3> <h3>体感温度: {res.main.feels_like} °F</h3> <h3>最低温度: {res.main.temp_min} °F</h3> <h3>最高温度: {res.main.temp_max} °F</h3> <h3>湿度: {res.main.humidity} %</h3>
如果需要兼容旧环境,也可以用短路判断:res.main && res.main.temp
修改后的完整Resort.js代码
import './App.css'; import React from 'react'; import axios from 'axios'; const url = 'https://api.openweathermap.org/data/2.5/weather' function Resort(props) { // 初始状态设为null,匹配API返回的对象类型 const [res, setRes] = React.useState(null) React.useEffect(() => { axios.get(url, { params: { lat: props.lat, lon: props.lon, appid: props.appid, units: "imperial" } }).then((response) => { setRes(response.data) console.log('temp: ', response.data.main.temp) }); }, [props]); // 数据未加载完成时显示加载提示 if (!res) return <div className="Resort">Loading weather data...</div>; return ( <div className='Resort'> <h1>{props.resortName}</h1> <h3>Lat: {props.lat} Lon: {props.lon}</h3> {/* 逐个渲染需要的字段 */} <h3>当前温度: {res.main.temp} °F</h3> <h3>体感温度: {res.main.feels_like} °F</h3> <h3>最低温度: {res.main.temp_min} °F</h3> <h3>最高温度: {res.main.temp_max} °F</h3> <h3>湿度: {res.main.humidity} %</h3> </div> ); } export default Resort;
额外优化建议
- 可以添加API请求错误处理,比如捕获axios的异常,显示错误信息:
axios.get(...).then(...).catch(err => { console.error('获取天气数据失败:', err); // 可以设置错误状态,在页面显示错误提示 })
- 给每个Resort组件添加唯一key,避免React警告:
{[...resorts.keys()].map((item)=>{ return <Resort key={item} resortName={item} lat={resorts.get(item)[0]} lon={resorts.get(item)[1]} appid={appId} /> })}
内容的提问来源于stack exchange,提问作者Grant
相关产品推荐
相关产品推荐

