Search code examples
reactjssetstate

setState inside for loop does not update the state: React+Typescript


I am having an array of objects which is a state object that corresponds to a user account. Just for a validation purpose if any one of the object property within array is empty, I am setting a validation property of state object to false. Since I am looping using for loop, the setState is not setting data.

 this.state = {
      accounts: [{firstname:"",lastname:"",age:""}],
      validated: true
 };


onAdd = () => {

    let { accounts,validated } =  this.state;
    for(let i=0; i< accounts.length; i++){
      if(accounts[i].firstname === '' || accounts[i].age === '')
      {
        this.setState({validated: false},() => {}); // value is not getting set
        break;
      }
    }
    if(validated)
    {
      // some other operation 
      this.setState({validated: true},() => {});
    }
  }

render(){

   let { validated } =  this.state;
   return(
     {validated ? <span>Please fill in the details</span> : null}
       //based on the validated flag displaying the error message
   )
}

Solution

  • There are multiple issues in your code. First of all this.setState is asynchronous and therefore you can not say when it really is executed.

    So if you call

    this.setState({validated: false},() => {});
    

    you can not rely that after that this.state.validated is false immediatly.

    So after you call this.setState to make validated == false and then check:

    if(this.state.validated)
    {
      // some other operation 
      this.setState({validated: true},() => {});
    }
    

    It might be either true or false.

    But in your code you're extracting validated (what you're using in the if-condition) at the beginning of your method. That means validated won't change when this.state changes.

    You might want to use the callback you already added (() => {}) to perform some other action after the state changed or just use a normal valiable instead of something related to the state.

    Like:

    tmp = true;
    
    for-loop {
      if(should not validate) {
        tmp = false;
        this.setState({validated: false});
        break;
      }
    
    if(tmp) {
      this.setState({validated: true},() => {});
    }