【问题标题】:TypeError: Cannot read properties of undefined (reading 'map') when calling from an APITypeError:从 API 调用时无法读取未定义的属性(读取“地图”)
【发布时间】:2021-10-16 01:00:33
【问题描述】:

我真的遇到了一个问题——如果你运行下面的代码你会得到一个错误“TypeError: Cannot read properties of undefined (reading 'map') ”。

当我在控制台注销“items”变量时,我得到 2 个结果,如下所示:

问题在于第一个结果,因为它是空的。但是有人可以向我解释为什么这个结果是空的以及为什么它会产生 2 个结果吗?

此代码直接取自 here,并进行了修改以适应 API 返回的内容。请考虑运行此代码,以便您了解我的意思。

import React, {useState, useEffect} from 'react';
import logo from './logo.svg';
import './App.css';

function App() {

  const [error, setError] = useState(null);
  const [isLoaded, setIsLoaded] = useState(false);
  const [items, setItems] = useState([]);

  useEffect(() => {
    fetch("http://www.7timer.info/bin/api.pl?lon=113.17&lat=23.09&product=astro&output=json")
  .then(res => res.json())
  .then(
    (result) => {
      setIsLoaded(true);
       setItems(result); 
    },
    // Note: it's important to handle errors here
    // instead of a catch() block so that we don't swallow
    // exceptions from actual bugs in components.
    (error) => {
      setIsLoaded(true);
      setError(error);
    }
  )
  }, [])


  if (error) {
    return <div>Error: {error.message}</div>;
  } else if (!isLoaded) {
    return <div>Loading...</div>;
  } else {
return (
  <ul>
    {items.dataseries.map(item => (
       {console.log(item)}
    ))}
</ul>
    );
  }
}

export default App;

【问题讨论】:

  • 您的items 状态变量在首次加载时没有dataseries 属性。在使用 map 渲染之前,您需要在渲染函数中检查它。

标签: javascript reactjs


【解决方案1】:

我可以看到两个错误

  1. 您要获取的数据是一个对象,而您最初将其设置为一个数组,并且您还使用了只能在数组上使用的 map 函数。
  2. 最初,您的数组不包含 dataseries,您也无法在数组中访问类似的属性(因为数组有索引,我们可以通过索引获得那里的值)。

所以你可以做的就是把这个函数设置成这样

useEffect(() => {
fetch("http://www.7timer.info/bin/api.pllon=113.17&lat=23.09&product=astro&output=json")
.then(res => res.json())
.then(
  (result) => {
  setIsLoaded(true);
   setItems(result.dataseries); 
},
// Note: it's important to handle errors here
// instead of a catch() block so that we don't swallow
// exceptions from actual bugs in components.
  (error) => {
    setIsLoaded(true);
    setError(error);
  }
)}, [])

返回函数是这样的

return (
  <ul>
    {items.map(item => (
      {console.log(item)}
    ))}
  </ul>
);

【讨论】:

  • 完美。你的答案解决了我的问题。但我很好奇,你知道为什么这个值会输出两次吗?另外,如果我将状态设置为对象并存储结果,为什么我不能在 map 函数中访问 items.dataseries?
  • 是的,因为 React 不能以首先等待所有请求被获取然后呈现内容的方式工作。每当组件被挂载时,它都会使用任何可用的内容进行渲染。所以最初你的项目指向一个空数组,array.map 工作但是当数组更改为对象时(当数据被获取并调用 setState 时)它不再具有映射函数,因为对象不支持映射函数。另外,这也是它输出两次的原因,因为第一次是组件被挂载,第二次是调用 setState 并且组件被重新渲染。
【解决方案2】:

Items 是一个数组而不是对象,例如 [{...}, {...}] ,desiredseries 在对象内部,而不是项目。

 <ul>
        {items.map(item => item.dataseries.map(ds=> (
           {console.log(ds)}
        )))}
    </ul>

【讨论】:

    猜你喜欢
    • 2021-12-20
    • 2021-07-13
    • 2022-01-14
    • 1970-01-01
    • 2021-11-17
    • 2022-01-12
    • 2021-11-09
    • 2021-06-25
    • 1970-01-01
    相关资源
    最近更新 更多