开发者问题收集

使用 axios 进行异步 API 调用后出现 TypeError

2021-04-09
109

我试图弄清楚我的代码中发生的一些事情。 我正在从我创建的 Rest API 中获取一些数据,在异步调用之后我得到了:

TypeError:无法读取未定义的属性“field”

我无法弄清楚发生了什么,因为当我在控制台上记录数据时,我可以看到我的对象填充了正确的信息。为了确保我没有犯类型错误,我从 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 次,因为我只是记录它一次。

2个回答

当 React 组件正在渲染时。它不会等待异步调用完成。当 React 组件首次挂载时,char 为空,但您从 char: "id"; "name" 获取属性值。因此,您需要添加一个异常,以确保何时使用 char 渲染组件角色并成功调用 API。

{char !== undefined (exceptions here) && }
Tommy Tang
2021-04-09

您需要使用 then()、catch() 处理承诺,以 阅读更多

解决方案是在组件准备就绪时通过使用 useEffect 调用 findRandomVillain() ,并使用 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;
Mohamed Ahmed
2021-04-09