开发者问题收集

TypeError: 无法读取未定义的属性“Countries”。为什么对象数组无法识别且无法过滤?

2021-06-04
232

我从 API ('https://api.covid19api.com/summary') 获取一个对象。此对象有一个 键 Countries,其中包含一个对象数组,我需要过滤这个对象数组。

const filteredData = data.Countries.filter(dat => {
        return dat.Country.toLowerCase().includes(searchfield.toLowerCase());
      })

TypeError: Cannot read property 'Countries' of undefined.

为什么无法识别和过滤对象数组? 在另一个文件中,map 方法迭代相同的写入 data.Countries 而没有错误。

const Home = () => {
    const [data, setData] = useState();
    const [searchfield, setSearchfield] = useState('')
    useEffect(() => {
        const fetch = async () => {
            try{
                const res = await axios.get('https://api.covid19api.com/summary');
                setData(res.data);
            }catch(error){
                console.log(error);
            }
        };
        fetch();
    }, []);
    
    const onSearchChange = (event) => {
        setSearchfield(event.target.value)
      }

      const filteredData = data.Countries.filter(dat => {
        return dat.Country.toLowerCase().includes(searchfield.toLowerCase());
      })   
    
     return (
        <div className="main-container">
            <Header searchChange={onSearchChange}/>
            <div className="wrapper">
                <Card data={data}/>
                {/*<div className="graph">
                    <h1>Global Pandemic Crisis Graph</h1>
                    <img src={COVID.image} alt=""/>
                </div>*/}
                <div className="countries">
                    <Countries data={filteredData}/>
                </div>
            </div>
            {/*<Footer />*/}
        </div>
    )
}
3个回答

当你从 API 获取数据时,你需要在将任何高阶函数应用于数组时使用可选链接 ? ,以防数据尚未加载。例如

const filteredData = data?.Countries.filter(dat => {
        return dat.Country.toLowerCase().includes(searchfield.toLowerCase());
      })
crispengari
2021-06-04

问题

初始 data 状态未定义,因此 data.Countries 在初始渲染时未定义。

const [data, setData] = useState();

解决方案

提供有效的初始状态并防止后续错误更新(如果发生)。

const [data, setData] = useState({ Countries: [] });

...

const filteredData = data?.Countries?.filter(dat => {
  return dat.Country.toLowerCase().includes(searchfield.toLowerCase());
})
Drew Reese
2021-06-04

您需要在 axios 响应的回调中过滤数据,否则它将是“未定义”的,因为它尚未完成获取。

let filteredData = useRef(null);
  useEffect(() => {
    if (typeof data !== "undefined")
      filteredData.current = data.Countries.filter((dat) => {
        return dat.Country.toLowerCase().includes(searchfield.toLowerCase());
      });
  }, [data]);

  const fetch = async () => {
    const res = await axios
      .get("https://api.covid19api.com/summary")
      .then((response) => {
        // response.data should not be "undefined" here.
        setData(response.data);
      })
      .catch((error) => {
        // Error fallback stuff
        console.error(error);
      });
  };
  if (!filteredData.current) fetch();

稍后您可以在代码中检查它是否已被定义,

return (
    <div className="main-container">
      <div className="wrapper">
        {filteredData.current !== null &&
          filteredData.current.map((CountryMap, i) => 
          <div key={i}>{CountryMap.Country}</div>
          )
        }
      </div>
    </div>
  );
Any Day
2021-06-04