Why Calling Setstate Method Doesn't Mutate the State Immediately

Why does calling react setState method not mutate the state immediately?

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);
});

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

Reason is setState is asynchronous, you can't expect the updated state value just after the setState, if you want to check the value use a callback method. Pass a method as callback that will be get executed after the setState complete its task.

Why setState is asynchronous ?

This is because setState alters the state and causes re rendering. This can be an expensive operation and making it synchronous might leave the browser unresponsive.
Thus the setState calls are asynchronous as well as batched for better UI experience and performance.

From Doc:

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.

Using callback method with setState:

To check the updated state value just after the setState, use a callback method like this:

setState({ key: value }, () => {
console.log('updated state value', this.state.key)
})

Check this:

class NightlifeTypes extends React.Component {   constructor(props) {      super(props);
this.state = { barClubLounge: false, seeTheTown: true, eventsEntertainment: true, familyFriendlyOnly: false } }
handleOnChange = (event) => { // Arrow function binds `this` let value = event.target.checked;
if(event.target.className == "barClubLounge") {
this.setState({ barClubLounge: value}, () => { //here console.log(value); console.log(this.state.barClubLounge); //both will print same value });
} }
render() { return ( <input className="barClubLounge" type='checkbox' onChange={this.handleOnChange} checked={this.state.barClubLounge}/> ) }}
ReactDOM.render(<NightlifeTypes/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'/>

setState doesn't update the state immediately

This callback is really messy. Just use async await instead:

async openAddBoardModal(){
await this.setState({ boardAddModalShow: true });
console.log(this.state.boardAddModalShow);
}

why setState only updates on mutating original state

for a given state that is an object or array, react uses only its reference to compare and decide if it will update state, it doesn't do deep comparision between objects values.

the first case you are passing the same reference, therefore there is no update state. actually, if you modify the array at first example, that's actually mutating state directly.

second case you are cloning into a new fresh array, which holds a different reference. since the reference is different from previous array, react now update its state. that's actually the right approach to update state when dealing with arrays/objects.

Why can't I directly modify a component's state, really?

The React docs for setState have this to say:

NEVER mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

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.

setState() will always trigger a re-render unless conditional rendering logic is implemented in shouldComponentUpdate(). If mutable objects are being used and the logic cannot be implemented in shouldComponentUpdate(), calling setState() only when the new state differs from the previous state will avoid unnecessary re-renders.

Basically, if you modify this.state directly, you create a situation where those modifications might get overwritten.

Related to your extended questions 1) and 2), setState() is not immediate. It queues a state transition based on what it thinks is going on which may not include the direct changes to this.state. Since it's queued rather than applied immediately, it's entirely possible that something is modified in between such that your direct changes get overwritten.

If nothing else, you might be better off just considering that not directly modifying this.state can be seen as good practice. You may know personally that your code interacts with React in such a way that these over-writes or other issues can't happen but you're creating a situation where other developers or future updates can suddenly find themselves with weird or subtle issues.

React setState not Updating Immediately

You should invoke your second function as a callback to setState, as setState happens asynchronously. Something like:

this.setState({pencil:!this.state.pencil}, myFunction)

However in your case since you want that function called with a parameter you're going to have to get a bit more creative, and perhaps create your own function that calls the function in the props:

myFunction = () => {
this.props.updateItem(this.state)
}

Combine those together and it should work.

React useState is always behind 1 step

setState actions are asynchronous and are batched for performance gains. This is explained in the documentation of setState

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 need to ensure ordering of events after a setState call is made, you can pass a callback function. this.setState({ something: true }, () => console.log(this.state))

React setState won't update

setState actions are asynchronous.

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.

You should use setState callback function:

this.setState({
location: {
name: 'Sigulda'
}
}, () => console.log(this.state.location));


Related Topics



Leave a reply



Submit