【问题标题】:Promise all and correctly update the state using React.js承诺所有并使用 React.js 正确更新状态
【发布时间】:2019-02-08 12:25:24
【问题描述】:

从 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]
          })
        }))))
  }
}

请指教我做错了什么。

【问题讨论】:

    标签: javascript reactjs api fetch es6-promise


    【解决方案1】:

    首先,当您尝试加载附加数据时,名称不会完成。

    只需使您的 componentDidMount 函数异步并等待每个调用(还要确保您为每个调用返回一个承诺)。

    async componentDidMount(){
      await this.loadPokemons();
      await this.loadPokemonAdditionalInfo();
    }
    

    您还返回结果的迭代,而不是每个结果的 json 数组。

    results.forEach(result => result.json()) 替换为:

    results.map(result => result.json()) in loadPokemonAdditionalInfo


    const results = [{ name:'John' }, { name:'Jane' }];
    
    console.log('forEach', results.forEach(result => result.name));
    console.log('map', results.map(result => result.name));

    【讨论】:

    • 非常感谢,但是这个使用 async-await 的操作没有帮助。有没有其他方法可以做到这一点?另外,为什么要使用 map 而不是 forEach?
    • forEach 函数只是迭代数组,不返回任何内容。您需要 map 函数将结果实际映射到新的名称数组。
    【解决方案2】:

    Promise.all 应该有数组或 promises,所以参数应该是 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]
        })
      })

    【讨论】:

      【解决方案3】:

      你不能同时运行

      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();
      }
      

      【讨论】:

      • 是的,现在可以使用了!哇!非常感谢您的解释和帮助!
      【解决方案4】:

      您的问题是,一旦您的组件挂载,您就会同时调用 loadPokemons 和 loadPokemonAdditionalInfo。您需要等到获取宠物小精灵名称后,才能获取它们的附加信息。

      this.loadPokemonAdditionalInfo() 应该从 setState 回调中调用,如

      this.setState({
         isLoaded: true,
          names: json.results
      }, this.loadPokemonAdditionalInfo)
      

      【讨论】:

      • 谢谢拉维和斯蒂芬!你是对的,对我帮助很大!现在可以了!
      猜你喜欢
      • 1970-01-01
      • 2022-01-10
      • 2021-11-26
      • 2013-10-06
      • 2021-08-17
      • 2021-06-27
      • 2017-10-25
      • 2017-01-15
      • 2019-04-29
      相关资源
      最近更新 更多