开发者问题收集

TypeError:无法使用 React 读取未定义的属性

2019-04-28
2547

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

TypeError: Cannot read property 'front_default' of undefined

我的组件如下所示:

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 属性的应用程序组件如下所示:

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。

3个回答

由于 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>
  );
};
ZHAOXIANLONG
2019-04-28

很可能只是 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;
Cat_Enthusiast
2019-04-28

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

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 服务器可以更改,我建议您即使在 @ZHAOXIANLONG 解决方案中也使用 lodash。

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

Doro
2019-04-28