繁体   English   中英

Promise all 并使用 React.js 正确更新状态

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM