我正在努力从React中的JSON数据构建一个Pokedex。我正在从我内置的jQuery中重构这个项目,所以可能是jQuery的方法使我误解了如何使用正确的React思维来解决这个问题。到目前为止,令我困扰的是如何基于我从父元素(这将是jQuery append
)传递的JSON动态呈现多个子元素。
这是我的App.js代码:
class App extends Component {
render() {
return (
<div className="App background">
<div className="content">
<Header />
<TilesContainer pokedexName="national"/>
</div>
</div>
);
}
TilesContainer本质上接收Pokedex的名称并调用API。各个口袋妖怪的名称都存储在TilesContainer状态(this.state.pokemon
)中的数组中,如下所示。
class TilesContainer extends Component {
constructor(props){
super(props);
this.state = {pokemon: []};
this.getPokemon = this.getPokemon.bind(this);
this.tiles = this.tiles.bind(this);
}
getPokemon() {
// set this.state.pokemon to the list
let link = 'https://pokeapi.co/api/v2/pokedex/' + this.props.pokedexName + '/';
fetch(link)
.then(response => response.json())
.then(myJson => {
let list = myJson['pokemon_entries'];
list.forEach(pokemon => {
this.state.pokemon.push(pokemon);
})
})
this.tiles();
}
tiles() {
if (this.state.pokemon.length > 0) {
return (
this.state.pokemon.map(pokemon => {
<Tile number={pokemon.entry_number}/>
})
)
}
}
render(){
this.getPokemon();
return (
<div id="tiles-container"
className="tiles-container">
<h1>TilesContainer Test</h1>
<Tile number={1} />
</div>
)
}
}
export default TilesContainer
同样,我们的想法是为Pokedex JSON中的每个Pokemon渲染一个Pokemon磁贴(目前我已将其存储在this.state.pokemon
中-不确定这是否是最佳方法)。我在此处的堆栈溢出示例中找到了一个使用附加功能的示例(本例this.tiles()
用于生成我认为是带有不同子元素的返回数组)。 <Tile number={1} />
是有关如何调用图块的硬编码示例。
当前,在代码运行时没有动态渲染的图块出现。这是正确的方法吗?我真的很感谢任何建议。
谢谢!
答案 0 :(得分:0)
因此,您是从父组件app.js传递pokedexName的,一旦获得道具,就可以在componentWillMount生命周期中调用rest api调用。
因此在渲染上,由于api调用已启动,因此不会包含任何数据,这就是为什么api调用完成后我们使用三元运算符检查数组的原因,并且我们获取了将数据设置为神奇宝贝的数据数组。
由于状态已更新,因此react将自动渲染一个re渲染,以便数据出现。
我希望以下代码能够解决此问题,请让我知道:)
// App.js
import React, { Component } from 'react';
import TilesContainer from './components/TileContainer/TilesContainer'
class App extends Component {
render() {
return (
<div>
<TilesContainer pokedexName="national" />
</div>
);
}
}
export default App;
// Tiles container
import React, {Component} from 'react';
import axios from 'axios';
class TilesContainer extends Component{
//state
state ={
pokemon: []
}
// life cycle methods
componentWillMount(){
let link = 'https://pokeapi.co/api/v2/pokedex/' + this.props.pokedexName + '/';
axios.get(link)
.then(res => {
this.setState({
pokemon: res.data["pokemon_entries"]
})
})
}
render(){
let style ={display:"inline"}
return(
<div>
{
this.state.pokemon.length > 0 ?
this.state.pokemon.map(pokemon => {
return(
<div key={pokemon.entry_number}>
<p style={style}>{pokemon.entry_number}</p>
<a href={pokemon.pokemon_species.url}>{pokemon.pokemon_species.name}</a>
</div>
)
})
:
null
}
</div>
)
}
}
export default TilesContainer
答案 1 :(得分:0)
好像你快到了。
首先,切勿直接修改state
。请改用this.setState()
。 React中的状态是异步更新的。出于您的目的,您应该可以像以下所示修改getPokemon()
。我也删除了this.tiles()
调用,因为这是不必要的。
getPokemon() {
// set this.state.pokemon to the list
let link = 'https://pokeapi.co/api/v2/pokedex/' + this.props.pokedexName + '/';
fetch(link)
.then(response => response.json())
.then(myJson => {
let list = myJson['pokemon_entries'];
this.setState({
pokemon: list,
});
})
}
对tiles()
的较小修正:使用箭头功能并返回一行内容时,请使用括号而不是花括号。当使用花括号时,必须包含一个return语句。有括号的话就没有。
tiles() {
if (this.state.pokemon.length > 0) {
return (
this.state.pokemon.map(pokemon => (
<Tile number={pokemon.entry_number}/>
))
)
}
}
接下来,由于tiles()
返回了动态磁贴组件,因此需要将其包含在render()
返回的内容中。
render(){
return (
<div id="tiles-container"
className="tiles-container"
>
<h1>TilesContainer Test</h1>
{this.tiles()}
</div>
)
}
最后,我认为对this.getPokemon()
的调用在构造函数中比在render()
中更有意义。
顺便说一句,我认为您获取json数据并将其存储在状态中的方法很好。将来,您可能想研究Redux来管理您的状态,但是对于一个很小的应用程序来说,这可能会显得过分杀伤。