[英]I am wondering why my useEffect data is empty on first render when I populate it on first render using useEffect
我正在使用 REST 国家/地区 API 创建一个应用程序,我使用 useEffect 挂钩在第一次渲染上调用 API 并使用我需要的数据填充我的 useState 数组。 当我尝试在组件的返回语句中访问此数据时,它读取为未定义。 我什至尝试添加一个三元运算符来首先检查数据是否为空,如果不是 output 它,但它仍然读取未定义但如果我注释掉代码并刷新页面,数据将被填充,然后可以取消注释代码以显示如果我再次刷新页面,数据读取为未定义。 我对为什么会发生这种情况感到非常困惑,因此非常感谢任何帮助。
我的.js文件:
const CountryInfo = () => {
const [data, setData] = useState([{}])
let countryName = window.location.pathname;
countryName = countryName.replace('/', '');
countryName = countryName.split('%20');
countryName = countryName.join(' ');
console.log(countryName)
useEffect(() => {
axios.get(`https://restcountries.com/v3.1/name/${countryName}`).then(response => {
console.log(response);
setData([{
name: countryName,
image: response.data[0].flags.png,
nativeName: response.data[0].name.nativeName.nld,
population: response.data[0].population,
region: response.data[0].region,
subRegion: response.data[0].subregion,
capital: response.data[0].capital[0],
borderCountries: response.data[0].borders,
topLevelDomain: response.data[0].tld[0],
currencies: response.data[0].currencies,
languages: response.data[0].languages,
}])
})
},[])
console.log(data)
return(
<div className='country-info-content'>
<Link to='/' className='info-button'>
<button className='button-info'>BACK</button>
</Link>
<div className='data-info'>
<img src={data[0].image} className='flag-img'/>
<div className='country-name'>
<span className='name'>{data[0].name}</span>
<div className='info-description'>
<div>
<div>
<span>Native Name:</span> {data[0].nativeName.common}
</div>
{/* {data?
<div>
<div>
<span className='title'>Native Name:</span> {data.nativeName.common}
</div>
<div>
<span className='title'>Population:</span> {data.population.toLocaleString(undefined)}
</div>
<div>
<span className='title'>Region:</span> {data.region}
</div>
<div>
<span className='title'>Sub Region:</span> {data.subRegion}
</div>
<div>
<span className='title'>Capital:</span> {data.capital}
</div>
</div>:null} */}
{/* {data ?
<div>
<span>Native Name: </span>{data[0].nativeName.common}
</div>: null
} */}
</div>
<div className='right-info'>
<div>
<span className='title'>Top Level Domain:</span> {data.topLevelDomain}
</div>
<div>
<span className='title'>Currency:</span> {data.topLevelDomain}
</div>
<div>
<span className='title'>Languages:</span> {data.topLevelDomain}
</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default CountryInfo;
useEffect将在您的页面第一次呈现后触发,这就是组件第一次呈现时未定义数据的原因。
您需要处理它,并且三元运算符是一种常见做法:
return data ? <div>...</div> : null;
或者
return data ? <div>...</div> : <div>Loading...</div>;
更新:错误消息是通过读取未定义的common
属性触发的。 你这样做的唯一地方是
data[0].nativeName.common
这意味着data[0]
存在,但nativeName
未定义。 nativeName
存储response.data[0].name.nativeName.nld,
的值。 您应该仔细检查从 API 返回的数据是否具有预期的格式并且是否设置了response.data[0].name.nativeName.nld
。
UPDATE2 :就像 Zeno 在评论中注意到的那样, data
的默认值是[{}]
,并且在三元运算符中始终评估为true
。
为什么在获取数据之前不设置默认undefined
?
还要确保将结果称为data[0]
,因为这是您存储响应的位置。 或者通过执行以下操作来简化您的代码:
setData({
name: countryName,
image: response.data[0].flags.png,
nativeName: response.data[0].name.nativeName.nld,
population: response.data[0].population,
region: response.data[0].region,
subRegion: response.data[0].subregion,
capital: response.data[0].capital[0],
borderCountries: response.data[0].borders,
topLevelDomain: response.data[0].tld[0],
currencies: response.data[0].currencies,
languages: response.data[0].languages,
})
无需在其中存储数组。
您有数据映射错误。 尝试在数据数组中设置本机名称时,您的数据设置不正确。
你有:
setData([
{
...
nativeName: response.data[0].name.nativeName.nld,
...
}
]);
并返回
<div>
<span className='title'>Native Name:</span> {data.nativeName.common}
</div>
但是 api 返回的数据结构看起来不同,例如:
data: Array(12)
0: Object
name: Object
common: "Eswatini"
official: "Kingdom of Eswatini"
nativeName: Object
eng: Object
ssw: Object
改为:
setData([
{
...
nativeName: response.data[0].name.common,
...
}
]);
和
<div>
<span>Native Name:</span> {data[0].nativeName}
</div>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.