[英]Promise all and correctly update the state using React.js
从 API 获取数据我得到这样的数据:
0: {name: "bulbasaur", url: "https://pokeapi.co/api/v2/pokemon-species/1/"}
1: {name: "ivysaur", url: "https://pokeapi.co/api/v2/pokemon- species/2/"}
2: {name: "venusaur", url: "https://pokeapi.co/api/v2/pokemon-species/3/"}
3: {name: "charmander", url: "https://pokeapi.co/api/v2/pokemon-species/4/"}
4: {name: "charmeleon", url: "https://pokeapi.co/api/v2/pokemon-species/5/"}
5: {name: "charizard", url: "https://pokeapi.co/api/v2/pokemon-species/6/"}
为了获得更详细的信息,我需要获取每个 url。 我正在尝试使用 Promise.all 并更新状态,但代码不起作用:
class App extends Component {
constructor(props) {
super(props);
this.state = {
pokemons: [],
names: [],
isLoaded: false
};
}
componentDidMount() {
this.loadPokemons();
this.loadPokemonAdditionalInfo();
}
loadPokemons() {
fetch('https://pokeapi.co/api/v2/pokemon-species')
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
names: json.results
})
})
}
loadPokemonAdditionalInfo() {
Promise.all(this.state.names.map(name =>
fetch(name.url)
.then(results => results.forEach(result => result.json())
.then(r => {
this.setState({
pokemons: [...this.state.pokemons, r]
})
}))))
}
}
请建议我做错了什么。
Promise.all 应该有 array 或 promises ,所以参数应该是 array of fetches 。
Promise.all(this.state.names.map(name => fetch(name.url))) .then(results => results.forEach(result => result.json()) .then(r => { this.setState({ pokemons: [...this.state.pokemons, r] }) })
您的问题是您在组件安装后立即调用 loadPokemons 和 loadPokemonAdditionalInfo 。 在获取它们的附加信息之前,您需要等到获取了口袋妖怪的名称。
this.loadPokemonAdditionalInfo()
应该从 setState 回调中调用,例如
this.setState({
isLoaded: true,
names: json.results
}, this.loadPokemonAdditionalInfo)
首先,当您尝试加载附加数据时,名称不会完成。
只需让你的componentDidMount
函数异步并等待每个调用(还要确保你为每个调用返回一个承诺)。
async componentDidMount(){
await this.loadPokemons();
await this.loadPokemonAdditionalInfo();
}
此外,您正在返回结果的迭代,而不是每个结果的 json 数组。
将results.forEach(result => result.json())
替换为:
loadPokemonAdditionalInfo
results.map(result => result.json())
loadPokemonAdditionalInfo
results.map(result => result.json())
const results = [{ name:'John' }, { name:'Jane' }]; console.log('forEach', results.forEach(result => result.name)); console.log('map', results.map(result => result.name));
你不能同时运行
this.loadPokemons();
this.loadPokemonAdditionalInfo();
以同步方式,setState 需要一些时间来改变状态。 这就是为什么有一个对 setState 的回调。
以下应该工作:
loadPokemons(){
fetch('https://pokeapi.co/api/v2/pokemon-species')
.then(res => res.json())
.then(json => {
this.setState({
isLoaded: true,
names: json.results
}, () => {
this.loadPokemonAdditionalInfo()
})
})
}
loadPokemonAdditionalInfo() {
const { names } = this.state;
const promises = names.map(
name => fetch(name.url).then(response => response.json())
)
Promise.all(promises).then(results => {
this.setState({
pokemons: [...this.state.pokemons, ...results]
})
})
}
componentDidMount(){
this.loadPokemons();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.