DJ2
DJ2

Reputation: 1741

Promise.all() problem using setTimeout(), state not updating

I have an arrow function that is invoked from cDM to retrieve the updated status of schedules every 20 seconds with a setTimeout().

componentDidMount() {
    //get request to /schedules
    //update state with response data
    this.getUpdatedStatus();
}

Each schedule present at /schedules looks like this:

"data": {
"id": "2147483605",
"selfUri": "/schedules/2147483605",
"type": "Schedule",
"status": "Pending",
}

So in the below method, each schedule.selfUri is requested, and I'm attempting to update status of each schedule.

    getUpdatedStatus = () => {
//fetch updated status,
const schedules = this.state.schedules;
Promise.all(
  schedules.map(schedule =>
    axios({
      method: "get",
      url: schedule.selfUri,
    })
  )
)
  .then(response => {
    console.log(response);
    const isIncomplete = response.some(r => r.status !== "Complete");
    console.log(isIncomplete);
    if (isIncomplete) {
      this.timeout = setTimeout(() => this.getUpdatedStatus(), 20000);
    }
    this.setState(
      {
        scheduleStatus: isIncomplete ? "Pending" : "Complete",
      },
      () => {
        console.log(this.state.scheduleStatus);
        console.log(this.state.schedules);
      }
    );
  })
  .catch(error => console.log(error.response));

};

The setTimeout function is working and requesting every 20 seconds to retrieve a possible update on the status. The object response eventually returns a status of complete but the value is not re-rendering in my table. I believe there is a problem with my promise chain and using setTimeout isn't updating my this.state.scheduleStatus when it completes. I have attached a codesandbox that gives a better view of my issue.

Codesandbox

Upvotes: 3

Views: 210

Answers (1)

Lennholm
Lennholm

Reputation: 7470

I don't think your problem has anything to do with the promise chain or using setTimeout(). I think it's caused by incorrectly getting the value for the isIncomplete flag, that it always gets set to true.

You're setting this value by the following line:

const isIncomplete = response.some(r => r.status !== "Complete")

I think the problem here is that you're expecting the response object to be the data you've specified, which contains a status property with a string value, while in reality it's the response object returned by Axios, where the statusproperty is the status code of the actual response (200 when successful). Therefore, isIncomplete is always true because r.status never equals "Complete".

Your data can be found in the data property and thus the aforementioned line should be like this:

const isIncomplete = response.some(r => r.data.status !== "Complete")

Upvotes: 3

Related Questions