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

Posted

技术标签:

【中文标题】TypeError:无法使用 React 读取未定义的属性【英文标题】:TypeError: Cannot read property of undefined using 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'变量会存储一个对象,不要给它分配一个空字符串。 【参考方案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: '' ;

【讨论】:

以上是关于TypeError:无法使用 React 读取未定义的属性的主要内容,如果未能解决你的问题,请参考以下文章

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

TypeError:无法读取未定义的属性“当前”(使用 React.js)

未处理的拒绝(TypeError):在 React 中使用 useRef 时无法读取未定义的属性(读取“值”)

React - TypeError:无法读取未定义的属性“img”

TypeError:无法读取 null 的属性(读取“推送”)react.js

React + Fetch + Json。 TypeError:无法读取未定义的属性