【问题标题】:React fetch data from API gives error Cannot read property of undefinedReact 从 API 获取数据给出错误无法读取未定义的属性
【发布时间】:2020-04-11 13:08:56
【问题描述】:

我正在使用 React Hook 通过本机 fetch 方法从 JSON 对象中获取数据。

const COVID_API_URL = "https://api.covid19api.com/summary";
const [infected, setInfected] = useState([]);

async function fetchData() {
  const response = await fetch(COVID_API_URL);

  response.json().then(response => setInfected(response));
}

useEffect(() => {
  fetchData();
}, []);

console.log(infected.Global.TotalConfirmed);

当我 console.log 来自 TotalConfirmed 的值时,我得到了正确的结果,但是当我刷新浏览器时,我不断得到:

TypeError: Cannot read property 'TotalConfirmed' of undefined

有人知道为什么会这样吗?我用的是 Gatsby.js 默认启动器,和这个有关系吗?

【问题讨论】:

  • 我无法理解接受的答案如何解决问题,因为这里的问题是您正在访问一个不存在的值。不要假设您将始终获得正确的数据,始终验证您的数据。

标签: javascript reactjs fetch react-hooks gatsby


【解决方案1】:

这里的问题是infected 状态的值异步到达。你可以做的是使用useEffect钩子。

尝试如下:

useEffect(() => {
   console.log(infected.Global.TotalConfirmed);
}, [infected]);

通过这样做useEffect 回调将在infected 值发生变化时触发-API 调用响应-因此在setInfected(response) 更新infected 状态的值之后。

我希望这会有所帮助!

【讨论】:

    【解决方案2】:

    第一次访问infected 时它仍然是未定义的,你需要做的就是在使用它之前验证变量。你不需要另一个useEffect

    console.log(infected && infected.Global && infected.Global.TotalConfirmed);
    

    const {useState, useEffect} = React;
    
    const COVID_API_URL = "https://api.covid19api.com/summary";
    
    function App() {
      const [infected, setInfected] = useState([]);
      const [isLoading, setIsLoading] = useState(true);
    
      function fetchData() {
        fetch(COVID_API_URL)
          .then(jsonResponse => jsonResponse.json())
          .then(response => {
            setIsLoading(false);
            setInfected(response);
          })
          .catch(e => {
            console.log("error", e);
            setIsLoading(false);
          });
      }
    
      useEffect(() => {
        fetchData();
      }, []);
    
      console.log(infected && infected.Global && infected.Global.TotalConfirmed);
      return (
        <div className="App">
          <h1>COVID-19 Summary</h1>
          {isLoading && <p>Getting data...</p>}
        </div>
      );
    }
    
    ReactDOM.render(
      <App />,
      document.getElementById("app")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
    <div id="app"></div>

    【讨论】:

      【解决方案3】:

      您可以添加一个新状态,例如我的示例 isFetched,然后将其默认值设置为 false

      const [isFetched,setIsFetched] = useState(false);
      

      然后在你的 setInfected(response) 之后使用 setIsFetched 函数 最后你可以检查 isFetched 是否为真,然后在你的代码中使用你的 api 数据(感染状态)。

      const COVID_API_URL = "https://api.covid19api.com/summary";
      const [infected, setInfected] = useState([]);
      const [isFetched,setIsFetched] = useState(false);
      
      async function fetchData() {
        const response = await fetch(COVID_API_URL);
      
        response.json().then(response => 
        {      
           setInfected(response));
           setIsFetched(true);
        }
      }
      
      useEffect(() => {
        fetchData();
      }, []);
      

      那么当你想在页面上显示 api 数据时:

      {
        isFetched ?
        // use api data : null
      }
      

      【讨论】:

        【解决方案4】:

        即使在使用 axios 之后,我也遇到了这个问题。它很容易修复,您只需要在返回之前添加 if else 语句。像这样

        `if(myArray.length > 0){
        return (data and everything)}
        else{return <h1>Loading</h1>}`
        

        【讨论】:

          猜你喜欢
          • 2022-01-16
          • 2019-02-28
          • 1970-01-01
          • 2017-01-18
          • 2018-10-22
          • 2018-12-22
          • 1970-01-01
          • 1970-01-01
          • 2021-11-14
          相关资源
          最近更新 更多