【问题标题】:Getting TypeError after Async API Call with axios使用 axios 进行异步 API 调用后出现 TypeError
【发布时间】:2021-07-04 22:30:53
【问题描述】:

我正在尝试找出我的代码中发生的一些事情。 我正在从我制作的 Rest API 中获取一些数据,在异步调用之后,我得到了:

TypeError: Cannot read property 'field' of undefined

我无法弄清楚发生了什么,因为当我在控制台上记录数据时,我可以看到我的对象填充了正确的信息。为了确保我没有犯类型错误,我从console.log(response) 复制了数据并创建了一个对象并且它工作了。

来电:

import axios from 'axios';

const url_service_villain = "https://some_url/"

export const findRandomVillain = async () => {
    try {
        const {data} = await axios.get(url_service_villain + "find/random");
        return await data
    } catch (err) {
        console.log(err);
    };
};

这里是我调用方法的地方:

import React from 'react';

import Character from './components/Character'

import {findRandomVillain} from './services/VillainService';

async function getRandomVillain(){
  const data = await findRandomVillain();
  console.log(data);
  return data;
}

function CharacterList(){ 
  const char = getRandomVillain();
  return (
    <section className="characterList">
      <Character key={char.id} images={char.images.md} name={char.name} powerstats={char.powerstats}/>
    </section>    
  )
};

export default CharacterList;

getRandomVillain() 方法上,console.log(data) 打印我想要的对象, 但是在CharacterList 上,我得到了上面列出的TypeError

我还在控制台窗口的顶部注意到以下内容:

Promise {<pending>}  App.js:17
Promise {<pending>}  App.js:17
App.js:20 Uncaught TypeError: Cannot read property 'md' of undefined
    at CharacterList (App.js:20)
...{/*long list of errors here*/}
{id: "123", name: "Sinestro", powerstats: {…}, images: {…}} App.js:11
{id: "123", name: "Sinestro", powerstats: {…}, images: {…}} App.js:11
{id: "123", name: "Sinestro", powerstats: {…}, images: {…}} App.js:11

我认为这与异步调用有关,我不知道为什么最后一行重复了 3 次,因为我只记录了一次。

【问题讨论】:

  • 您在哪里尝试访问某个东西的field?你提到的唯一地方是在错误消息中,而不是在代码中
  • 在函数CharacterList()上,有一个const char接收数据。我猜。

标签: reactjs async-await axios


【解决方案1】:

当反应组件正在渲染时。它不会等待异步调用完成。当第一次安装 react 组件时,char 是空的,但是您从 char: "id"; 获取属性值; “姓名”。因此,您需要添加一个异常,以确保何时使用 char 渲染组件字符并成功调用 API。

{char !== undefined (这里有例外) && }

【讨论】:

    【解决方案2】:

    您需要使用then(), catch()Read more 处理承诺

    解决方案是在组件准备就绪时调用findRandomVillain(),方法是使用useEffect 并使用useState 设置char

    import React, { useEffect, useState } from "react";
    
    import Character from "./components/Character";
    
    import { findRandomVillain } from "./services/VillainService";
    
    function CharacterList() {
      const [char, setChar] = useState();
    
      // using useEffect to make sure component is Ready
      useEffect(() => {
        findRandomVillain()
          .then((res) => setChar(res)) // handle promising
          .catch((err) => console.log(err));
      }, []);
    
      if (!char) return <div>loading</div>;
      
      return (
        <section className="characterList">
          <Character
            key={char.id}
            images={char.images.md}
            name={char.name}
            powerstats={char.powerstats}
          />
        </section>
      );
    }
    
    export default CharacterList;
    

    【讨论】:

    • 可以把useEffect放在第一段代码上,也就是执行api调用的地方,是不是一个好习惯?
    • 是的,这是一个很好的做法,功能组件中的useEffect 与类组件中的componentDidMount() 相同,您需要在组件准备好时调用您的req
    猜你喜欢
    • 2018-11-25
    • 2021-07-17
    • 2016-12-12
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 2019-04-06
    • 1970-01-01
    • 2017-11-07
    相关资源
    最近更新 更多