【问题标题】:TypeError: Cannot read property of undefined using ReactTypeError:无法使用 React 读取未定义的属性
【发布时间】:2019-09-17 03:15:53
【问题描述】:

我是 React 的新手,我正在使用 PokeAPI 做一个小应用程序。我有一个名为 PokemonDetail 的组件,我想在其中显示一个 pokemon 的详细信息,但该应用程序向我抛出了下一个错误

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

我的组件如下所示:

import React from "react";

const PokemonDetail = ({ pokemon }) => {
  return (
    <div>
      <div className="text-center">{pokemon.name}</div>
      <img src={pokemon.sprites.front_default} alt={pokemon.name} />
      {pokemon.id}
    </div>
  );
};

export default PokemonDetail;

PokemonDetail 接收 pokemon 道具的 App 组件如下所示:

import React from "react";
import PokeAPI from "../apis/PokeAPI";
import SearchBar from "./SearchBar";
import PokemonDetail from "./PokemonDetail";

class App extends React.Component {
  state = { pokemon: '' };

  onTermSubmit = async term => {
    try {
      const response = await PokeAPI.get(`pokemon/${term}`);
      this.setState({ pokemon: response.data });
      console.log(response);
    } catch (error) {
      console.log("No existe");
    }
  };

  render() {
    return (
      <div className="container">
        <div className="row mt-3">
          <div className="col">
            <SearchBar onFormSubmit={this.onTermSubmit} />
          </div>
        </div>
        <div className="row mt-3">
          <div className="col-9" />
          <div className="col-3">
            <PokemonDetail pokemon={this.state.pokemon} />
          </div>
        </div>
      </div>
    );
  }
}

export default App;

我不明白为什么它会抛出这个错误,因为它只会抛出这个和 json 的其他属性。 name 属性有效,等到我向它发送一些道具,id 相同,但 front_default 属性没有,这是图像的 url。

【问题讨论】:

  • 如果你知道'pokemon'变量会存储一个对象,不要给它分配一个空字符串。

标签: javascript ajax reactjs api


【解决方案1】:

因为ajax比react渲染慢,所以可以在获取数据之前使用加载组件。

const PokemonDetail = ({ pokemon }) => {
  if(pokemon.sprites == undefined){
      return(
        <div>
            Loading...
        </div>
      );
  }
  return (
    <div>
      <div className="text-center">{pokemon.name}</div>
      <img src={pokemon.sprites.front_default} alt={pokemon.name} />
      {pokemon.id}
    </div>
  );
};

【讨论】:

    【解决方案2】:

    很可能只是 AJAX 问题,您的组件在有时间完成您对 API 的请求之前呈现。尝试在渲染图像之前添加额外的检查。

    import React from "react";
    
    const PokemonDetail = ({ pokemon }) => {
      return (
        <div>
          <div className="text-center">{pokemon.name}</div>
           {pokemon.sprites ? (
            <img src={pokemon.sprites.front_default} alt={pokemon.name} />
            ) : ( 
              null
            )
           }
          {pokemon.id}
        </div>
      );
    };
    
    export default PokemonDetail;
    

    【讨论】:

    • 但是为什么使用 json 的某些属性而使用其他属性会抛出错误?
    • 你知道,我希望我有更好的解释方式,但有时当你与 API 通信时,它只需要一些属性的加载时间比其他属性长:/
    【解决方案3】:

    @ZHAOXIANLONG 给了你最好的解决方案(使用加载组件,直到你收到数据),但是,如果你不使用加载组件,你可以使用 lodash 的 get 方法 库 [1] 以避免可能的错误。

    import React from "react";
    import _ from 'lodash';
    
    const PokemonDetail = ({ pokemon }) => {
        const front_default = _.get(pokemon, 'sprites.front_default', 'DEFAULT_VALUE');
        const name = _.get(pokemon, 'name', 'DEFAULT_VALUE');
    
        return (
            <div>
                <div className="text-center">{pokemon.name}</div>
                <img src={pokemon.sprites.front_default} alt={pokemon.name} />
                {pokemon.id}
            </div>
        );
    };
    
    export default PokemonDetail;
    

    其中第三个参数 ('DEFAULT_VALUE') 是一个默认值,如果 lodash 无法为您的查询检索值,将使用该值。

    PS:如果您知道您的 API Server 可以更改,我建议您即使在 @ZHAOXIANLONG 解决方案中也使用 lodash。

    [1]https://lodash.com/docs/4.17.11#get

    【讨论】:

      【解决方案4】:

      初始状态为{ pokemon: '' }pokemon 是一个空字符串。 PokemonDetail 指的是pokemon.sprites.front_default,但pokemon 最初是一个字符串,而字符串没有名为sprites 的字段。

      如果你希望 pokemon 最终成为一个对象,你可以将它初始化为一个看起来像一个对象的东西:

      state = { pokemon: { sprites: {front_default: '' }}};
      

      【讨论】:

        猜你喜欢
        • 2023-04-01
        • 2021-09-24
        • 2020-07-10
        • 2019-07-07
        • 2021-03-10
        • 2020-02-10
        • 2021-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多