Reputation: 24925
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
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
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