Calling setState in a loop only updates state 1 time

Is there a reason that calling setSate() in a loop would prevent it from updating the state multiple times?

I have a very basic jsbin that highlights the problem I am seeing. There are two buttons. One updates the state's counter by 1. The other calls the underlying function of One in a loop -- which seemingly would update the state multiple times.

I know of several solutions to this problem but I want to make sure that I am understanding the underlying mechanism here first. Why can't setState be called in a loop? Do I have it coded awkwardly that is preventing the desired effect?

Answers:

Answer

There's a nice way to update state in a loop. Just make an empty variable, set its value to the updated state, call setState(), and pass it this variable:

const updatedState = {};

if (vars.length) {
  vars.forEach(v => {
    updatedState[v] = '';
    this.setState({
      ...this.state
      ...updatedState,
    });
  });
}
Answer

Basically setState is called asynchronously. It also has a callback function which you can utilise to do something once the state has been mutated. Also if multiple setStates are called one after the other they are batched together as written previously.

Answer

I was able to make your code work, calling setState in the loop by doing the following:

 manyClicks() {
   for (i = 0; i < 100; i++) {
     this.setState({clicks: this.state.clicks += 1})
   }
 }
enter code here

Hopefully this helps!

Answer

From the React Docs:

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value. There is no guarantee of synchronous operation of calls to setState and calls may be batched for performance gains.

Basically, don't call setState in a loop. What's happening here is exactly what the docs are referring to: this.state is returning the previous value, as the pending state update has not been applied yet.

Answer

I had the same problem. But tried with a little different approach.

iterateData(data){
  //data to render
   let copy=[];
   for(let i=0;<data.length;i++){
     copy.push(<SomeComp data=[i] />) 
    }
    this.setState({
      setComp:copy
    });
 }
 render(){
   return(
     <div>
       {this.state.setComp}
    </div>
   );
 }

I hope this helps.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.