我是React的新手,我正在用PokeAPI做一个小应用程序。我有一个名为PokemonDetail的组件,其中我想显示一个小精灵的细节,但该应用程序会抛出下一个错误
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;
口袋妖怪细节接收口袋妖怪道具的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
属性,这是一个图像的网址。
由于ajax比反应渲染慢,因此您可以在获取数据之前使用加载组件。
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>
);
};
很可能只是一个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;
@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。
最初的状态是{ pokemon: '' }
; pokemon
是一个空字符串。 PokemonDetail
指的是pokemon.sprites.front_default
,但pokemon
最初是一个字符串,而一个字符串没有一个名为sprites
的字段。
如果你期望pokemon最终成为一个对象,你可以将它初始化为看起来像一个对象的东西:
state = { pokemon: { sprites: {front_default: '' }}};