Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why calling react setState method doesn't mutate the state immediately?

I'm reading Forms section of reactjs documentation and just tried this code to demonstrate onChange usage (JSBIN).

var React= require('react');  var ControlledForm= React.createClass({     getInitialState: function() {         return {             value: "initial value"         };     },      handleChange: function(event) {         console.log(this.state.value);         this.setState({value: event.target.value});         console.log(this.state.value);      },      render: function() {         return (             <input type="text" value={this.state.value} onChange={this.handleChange}/>         );     } });  React.render(     <ControlledForm/>,   document.getElementById('mount') ); 

When I update the <input/> value in the browser, the second console.log inside the handleChange callback prints the same value as the first console.log, Why I can't see the result of this.setState({value: event.target.value}) in the scope of handleChange callback?

like image 358
Salah Eddine Taouririt Avatar asked Jun 11 '15 13:06

Salah Eddine Taouririt


People also ask

Why React setState setState does not update immediately?

State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.

Why are we using setState whereas not mutating the state?

Instead, we should use setState() . One reason is, for a pure component, directly mutating state won't trigger the component re-render, which could cause some odd bugs. With setState() we can change the state without directly mutating it.

Does setState work immediately?

setState or useState do not immediately mutate the state but create a pending state transition. Accessing state immediately after calling the updater method can potentially return the old value.

Why should we not mutate States directly in React?

React compares the previous state with the updated state to decide if the component needs to be re-rendered. Modifying the state directly will disturb this process. As a result the component will behave unexpectedly. In some cases not re-rendering at all even though the state has been modified.


2 Answers

From React's documentation:

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.

If you want a function to be executed after the state change occurs, pass it in as a callback.

this.setState({value: event.target.value}, function () {     console.log(this.state.value); }); 
like image 138
Michael Parker Avatar answered Sep 17 '22 18:09

Michael Parker


As mentioned in the React documentation, there is no guarantee of setState being fired synchronously, so your console.log may return the state prior to it updating.

Michael Parker mentions passing a callback within the setState. Another way to handle the logic after state change is via the componentDidUpdate lifecycle method, which is the method recommended in React docs.

Generally we recommend using componentDidUpdate() for such logic instead.

This is particularly useful when there may be successive setStates fired, and you would like to fire the same function after every state change. Rather than adding a callback to each setState, you could place the function inside of the componentDidUpdate, with specific logic inside if necessary.

// example componentDidUpdate(prevProps, prevState) {   if (this.state.value > prevState.value) {     this.foo();     } } 
like image 34
Yo Wakita Avatar answered Sep 17 '22 18:09

Yo Wakita