React state渲染异常提示Cannot read properties of undefined (reading 'country')如何解决
问题原因
你遇到的报错是典型的异步数据请求与组件渲染时序不匹配导致的:
- 组件首次渲染时,
covid的初始值是空对象{},此时直接访问covid.All会得到undefined,继续读取undefined.country就会抛出TypeError: Cannot read properties of undefined (reading 'country')错误 - 接口请求是异步执行的,报错不稳定的原因是:如果接口响应速度快,在首次渲染执行前就完成了数据赋值,就不会触发报错;如果渲染时请求还未完成,就会直接触发错误。刷新、热更新时请求和渲染的先后顺序不固定,所以异常表现时有时无。
解决方案
下面给出3种常用的修复方案,可根据需求选择:
方案1:使用可选链操作符(最简便)
直接修改渲染逻辑,用可选链?.做属性访问的安全兜底,属性不存在时会直接返回undefined,不会抛出错误,等数据请求完成后会自动正常渲染:
return ( <div> <h1>{covid?.All?.country}</h1> <h1>{covid?.All?.population}</h1> </div> );
方案2:增加初始值兜底
给state设置符合结构的初始值,避免首次渲染时访问不存在的属性:
// 把初始空对象改为带All属性的对象 const [covid, setCovidData] = useState({ All: {} })
方案3:增加加载状态判断(体验最优)
新增加载状态,请求未完成时渲染加载提示,请求完成后再渲染实际内容,同时还能避免无意义的空渲染:
修改后的完整App.js代码如下:
import api from './api/fetchCovidData' import { useState, useEffect } from 'react' const App = () => { const [covid, setCovidData] = useState({}) const [loading, setLoading] = useState(true) const [error, setError] = useState('') useEffect(() => { const fetchCovidData = async () => { try{ const response = await api.get('/cases?country=France'); setCovidData(response.data); setError('') } catch (err) { if (err.response){ // 不在200响应码区间 console.log(err.response.data); console.log(err.response.status); console.log(err.response.headers); setError('数据请求失败') } else { console.log(`Error: ${err.message}`); setError(`请求异常:${err.message}`) } } finally { setLoading(false) } } fetchCovidData(); }, []); if(loading) return <div>数据加载中...</div> if(error) return <div>{error}</div> return ( <div> <h1>{covid.All.country}</h1> <h1>{covid.All.population}</h1> </div> ); } export default App;
内容的提问来源于stack exchange,提问作者test me
相关产品推荐
相关产品推荐

