setState not working with forloop in react function

前端 未结 2 1401
萌比男神i
萌比男神i 2021-01-27 16:09

I am nesting two api calls inside componentDidMount, everything working fine, the only issue I have is the state do not update so I put some console logs to see what\'s going on

相关标签:
2条回答
  • 2021-01-27 16:52

    As you can see the state of loaded never get updated

    Because the setState happens asynchronous (not immediately update), using console.log(this.state.loaded) like that won't work as expected, instead, you might use the setState callback as you did with the second fetch, like so:

    this.setState(
      {
        data: data,
        loaded: true,
        loading: false
      },
      () => {
        console.log('analysis done!');
        console.log(this.state.loaded);
      }
    );
    

    EDIT

    I think we should use Promise.all() to make it work, like this:

      componentDidMount() {
        this.setState({ loading: true });
        fetch('https://url-one.com', {
          headers: {
            'Content-Type': 'application/json',
            'Access-Control-Allow-Origin': '*',
            'X-Spree-Token': 'xxx'
          }
        })
          .then(response => response.json())
          .then(responseJson => {
            console.log('fetch reviews done!');
            this.setState(
              {
                list: responseJson.reviews
              },
              () => {
                var obj = this.state.list;
                var data = [];
                var fetchArr = [];
                for (let i in obj) {
                  let promise = fetch('https://url-two.com', {
                    method: 'POST',
                    headers: {
                      Accept: 'application/json',
                      'Content-Type': 'application/json'
                    },
                    body: JSON.stringify({
                      api_key: 'uuu',
                      data: obj[i].text
                    })
                  }).then(response => response.json());
    
                  fetchArr.push(promise);  // make an array of promises
                }
    
                Promise.all(fetchArr).then(values => {   //after all promises resolved, we'll receive an array of responseJson, we'll loop through it
                  values.forEach((responseJson, i) => { //for each responseJson, we push it to the data array
                    data.push({
                      review: obj[i].text,
                      analysis: responseJson.results * 100
                    });
                  });
                  // finally, we update state
                  this.setState(
                    {
                      data: data,
                      loaded: true,
                      loading: false
                    },
                    () => {
                      console.log('analysis done!');
                      console.log(this.state.loaded);
                    }
                  );
                });
              }
            );
          });
      }
    
    0 讨论(0)
  • 2021-01-27 17:05

    You have a couple conflicting processes here that need to get shored up. You don't want to modify state during async actions because internally you will fire off a re-render, so I'd suggest reorganizing a bit. The loaded state is not resolving correctly because you aren't waiting for your subsequent requests to finish. Here is an example:

    0 讨论(0)
提交回复
热议问题