Rajesh
Rajesh

Reputation: 24925

How does update to state internally using setState in react?

In React, we use setState to update the state of the component. setState is an async process, so if we have multiple setState in same function.

Question: How is the batching of update handled internally?


Scenario 1:

Updating the state in a for loop in componentDidMount but in same execution cycle.

class TodoApp extends React.Component {
  constructor(props) {
    super(props)
    var state = { count: 0 };
    Object.defineProperty(this, 'state', {
    	set: function(value) { console.log('called', value.count); state = value },
      get: function() { return state; }
    })
  }
  
  test() {
  	for (let i = 0; i< 1000; i++) {
      this.setState({ count: i });
    }
  }
  
  componentDidMount() {   
    this.test();
  }
  
  render() {
    return (
      <div>
        { this.state.count }
      </div>
    )
  }
}

ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>


Scenario 2:

Updating the state in a for loop in componentDidMount but in different execution cycle.

class TodoApp extends React.Component {
  constructor(props) {
    super(props)
    var state = { count: 0 };
    Object.defineProperty(this, 'state', {
    	set: function(value) { console.log('called', value.count); state = value },
      get: function() { return state; }
    })
  }
  
  test() {
  	for (let i = 0; i< 1000; i++) {
      this.setState({ count: i });
    }
  }
  
  componentDidMount() {   
    setTimeout(this.test.bind(this), 0);
  }
  
  render() {
    return (
      <div>
        { this.state.count }
      </div>
    )
  }
}

ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>


If you notice scenario 1 and 2, in scenario 1 only 2 updates (assuming 1 for initial update and other for final) are performed. However, in scenario 2, state is mutated/ updated for every setState.

So how is the async update working? What defines the batch update action?

Upvotes: 1

Views: 142

Answers (2)

Vinit Kumar
Vinit Kumar

Reputation: 11

If you want batchUpdate by using setState then you should go with sync setState. There is a pre-defined way which can make our setState sync.

I'm little confused with your explanation but as per react documentation says itself we should not set multiple state into one function. because it will cause to re-render every time. which is not a good approach though.

so here is your count state which you want to set but in a sync way. then you might prefer

this.setState(prevState=>{
const {count}=prevState;
//perform any action with this count state and at the end 
return {...prevState,count};})

Hope this approach may help you.

Upvotes: 0

Dyo
Dyo

Reputation: 4464

They will be batched together if you are inside a React event handler. React batches all setStates done during a React event handler, and applies them just before exiting its own browser event handler.

setTimeout is not a React event handler so React won't batch state updates inside a setTimeout callback (scenario 2).

Reference : https://github.com/facebook/react/issues/10231#issuecomment-316644950

Upvotes: 4

Related Questions