javascript - 在 React 中动态添加子元素(状态数组)
问题描述
我正在努力从 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。各个 Pokemon 名称存储在 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 中的每个口袋妖怪渲染一个口袋妖怪图块(现在我已经存储了this.state.pokemon
- 不确定这是否是最好的方法)。我在 Stack Overflow 上找到了一个示例,它使用了一个附加函数(这种情况下this.tiles()
生成我认为是具有不同子元素的返回数组)。这<Tile number={1} />
是如何调用磁贴的硬编码示例。
目前,当代码运行时,不会显示动态渲染的图块。这是正确的方法吗。我真的很感激任何建议。
谢谢!
解决方案
因此,您从父组件 app.js 传递 pokedexName,一旦您获得道具,您就可以在 componentWillMount 生命周期中调用 rest api 调用。
所以在渲染上,因为 api 调用已经启动,所以它不会有任何数据,这就是为什么我们使用三元运算符来检查数组,一旦 api 调用完成并且我们得到我们正在将数据设置到 pokemon 数组的数据。
由于状态已更新,react 将自动渲染重新渲染,因此数据将出现。
我希望下面的代码能解决这个问题,请告诉我:)
// 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
推荐阅读
- alarm - 如何停止触发过去几天/时间的警报
- spring - 我可以配置 Spring Cloud Contract Pact 测试生成来处理 URL 路径中的上下文吗
- jquery - 如何等到变量不为空
- python-2.7 - 检测多个人脸 OpenCV
- salesforce - Lightning Web 组件在联系人详细信息页面中不起作用
- java - 在我的 Spring Batch 作业中禁用事务
- swift - 如何在mapView iOS中删除两个注释之间的覆盖
- android - NDK 编码中 OpenCV 的未定义参考错误太多
- asp.net-mvc - 是否有可能出现短暂的 SSL 错误?
- vba - DASL 中的 Outlook 附件名称