Reactjs访问state中存储的axios返回数组数据报错如何解决
问题根因
- 重渲染死循环问题:如果你直接在组件渲染流程中调用
setState存储映射结果,setState会触发组件重渲染,重渲染又会再次执行setState,形成无限循环,就会触发too many re-renders错误。 - 读取undefined属性报错问题:
- 组件首次渲染时,接口还没返回数据,
countriesList是空数组,此时通过filter匹配国家会得到空数组,你直接访问border[0].name时,border[0]为undefined,自然会报错。 - 你写的长度判断逻辑完全无效:
borderCountries是你主动往里面推和props.data长度一致的项,不管有没有匹配到国家,长度永远相等,等于没做判断。 filter是返回符合条件的数组,此处你只需要匹配单个对应国家,用filter反而多套了一层数组,逻辑冗余容易出错。- 你在
map中只写了console.log没有返回国家名称,最终返回的数组全是undefined,也没法正常渲染。
- 组件首次渲染时,接口还没返回数据,
修复方案
优先用useMemo缓存计算结果,不需要额外声明state就能避免重复计算,也不会触发死循环;同时增加加载状态判断和匹配容错,避免访问undefined属性。
修正后代码如下:
import axios from "axios"; import { useState, useEffect, useMemo } from "react"; const BorderCountries = (props) => { const [countriesList, setCountriesList] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { axios .get(`https://restcountries.com/v3.1/all`) .then((countries) => { setCountriesList(countries.data); setIsLoading(false); }) .catch((error) => { console.log(`${error}`); setIsLoading(false); }); }, []); // 用useMemo缓存计算结果,只有依赖项变化时才重新计算 const borderCountryNames = useMemo(() => { // 还在加载或者没有传入边境代码时直接返回空 if (isLoading || !props.data?.length) return []; return props.data.map(code => { // 用find直接找匹配的单个国家,不用filter套数组 const matchCountry = countriesList.find(country => country.cca3 === code); // 匹配不到的情况做兜底,避免报错 return matchCountry ? matchCountry.name.common : code; }); }, [isLoading, countriesList, props.data]); return ( <div> <h3>Border Countries:</h3> {isLoading ? <span>加载中...</span> : borderCountryNames.join('、')} </div> ); }; export default BorderCountries;
如果确实需要把结果存在state里,只需要把计算逻辑放到useEffect里,监听countriesList和props.data的变化触发更新即可,不会触发死循环:
// 额外声明state存结果的写法 const [borderNames, setBorderNames] = useState([]); useEffect(() => { if (isLoading || !props.data?.length) return; const names = props.data.map(code => { const matchCountry = countriesList.find(country => country.cca3 === code); return matchCountry ? matchCountry.name.common : code; }); setBorderNames(names); }, [isLoading, countriesList, props.data]);
内容的提问来源于stack exchange,提问作者ihatepineapple
相关产品推荐
相关产品推荐

