切换国家状态调用OpenWeatherMap API获取天气时出现TypeError错误的技术求助
解决React中切换国家时天气数据访问的TypeError问题
这个问题很常见,根源在于你的组件在初始渲染或者切换国家后,axios请求还没返回数据时,weather对象的main属性还不存在,导致访问weather.main.temp时抛出Uncaught TypeError: Cannot read properties of undefined (reading 'temp')错误。下面给你几种实用的解决办法:
1. 使用可选链操作符(最简洁)
ES2020引入的可选链操作符?.可以在访问嵌套属性时自动处理undefined/null的情况,如果链上的某个属性不存在,会直接返回undefined而不报错。修改你的温度渲染代码即可:
const WeatherInfo = ({ country }) => { const [weather, setWeather] = useState({}); useEffect(() => { axios .get(`https://api.openweathermap.org/data/2.5/weather?q=${country.capital}&appid=${api_key}&units=imperial`) .then(response => { console.log(response.data) setWeather(response.data) }) }, [country]) return ( <div> <h3>Weather in {country.capital}</h3> <p><b>Temperature</b>: {weather.main?.temp} °F</p> </div> ) }
2. 条件渲染(更直观)
通过检查weather.main是否存在,再决定是否渲染温度相关内容,避免在数据未就绪时访问不存在的属性:
const WeatherInfo = ({ country }) => { const [weather, setWeather] = useState({}); useEffect(() => { axios .get(`https://api.openweathermap.org/data/2.5/weather?q=${country.capital}&appid=${api_key}&units=imperial`) .then(response => { console.log(response.data) setWeather(response.data) }) }, [country]) return ( <div> <h3>Weather in {country.capital}</h3> {/* 只有当weather.main存在时才渲染温度 */} {weather.main && ( <p><b>Temperature</b>: {weather.main.temp} °F</p> )} </div> ) }
3. 初始化state时设置默认结构
你可以在初始化weather状态时,给它一个和API返回结构一致的默认值,这样初始渲染时就不会出现属性不存在的情况:
const WeatherInfo = ({ country }) => { // 初始化时给main和temp一个默认值 const [weather, setWeather] = useState({ main: { temp: 'Loading...' } }); useEffect(() => { axios .get(`https://api.openweathermap.org/data/2.5/weather?q=${country.capital}&appid=${api_key}&units=imperial`) .then(response => { console.log(response.data) setWeather(response.data) }) }, [country]) return ( <div> <h3>Weather in {country.capital}</h3> <p><b>Temperature</b>: {weather.main.temp} °F</p> </div> ) }
进阶:添加加载和错误处理(提升用户体验)
为了让用户更清楚当前状态,你可以添加加载状态和错误处理,避免数据未返回时页面显示空白或奇怪的内容:
const WeatherInfo = ({ country }) => { const [weather, setWeather] = useState({}); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); useEffect(() => { // 切换国家时重置状态 setLoading(true); setError(null); axios .get(`https://api.openweathermap.org/data/2.5/weather?q=${country.capital}&appid=${api_key}&units=imperial`) .then(response => { console.log(response.data) setWeather(response.data) }) .catch(err => { setError('Failed to fetch weather data'); console.error('Weather fetch error:', err); }) .finally(() => { setLoading(false); }) }, [country]) // 加载中状态 if (loading) return <div>Loading weather data for {country.capital}...</div>; // 错误状态 if (error) return <div className="error">{error}</div>; return ( <div> <h3>Weather in {country.capital}</h3> <p><b>Temperature</b>: {weather.main?.temp} °F</p> </div> ) }
内容的提问来源于stack exchange,提问作者aher98
相关产品推荐
相关产品推荐

