Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it ok to modify part of prevState inside setState?

Tags:

reactjs

Is there a real disadvantage to modifying part of prevState and returning that part inside setState() ?

Example:

this.setState(prevState => {
    prevState.myObject.isItTrue = !prevState.myObject.isItTrue;
    return {myObject: prevState.myObject};
});

Rather than:

this.setState(prevState => {
    const myObject = Object.assign({}, prevState.myObject);
    myObject.isItTrue = !myObject.isItTrue;
    return {myObject: myObject};
});

Is there any real disadvantage to the first code where I save myself the Object.assign() ?

EDIT: If I am correct, prevState.myObject is simply a reference to this.state.myObject, so changing prevState.myObject actually changes this.myObject.object as well! However, this doesn't seem to break anything, as long as I use setState() to pass an object that contains the new data, even if it's just a reference to the old objects inside this.state. Do you agree that this is still ok, i.e. it won't break anything to do it like this?

like image 257
Student Avatar asked Dec 17 '22 17:12

Student


2 Answers

Following documentation:

state is a reference to the component state at the time the change is being applied. It should not be directly mutated. Instead, changes should be represented by building a new object based on the input from state and props.

https://reactjs.org/docs/react-component.html

So you should not apply changes directly to that state.

Either way, why not do something like this?:

this.setState(prevState => ({
    myObject : {
        ...prevState.myObject,
        isItTrue: !prevState.myObject.isItTrue,
    }
}));

This way will get all the elements from the prevState but also change all the ones you want to modify.

like image 92
Jose A. Ayllón Avatar answered Jan 23 '23 21:01

Jose A. Ayllón


First prevState and the this.state are the same object. So you are modifying the actual state directly.

Secondly, down the road you might pass the myObject as a prop to another component, and since it will be the same object always that component will not know that something has changed and it will not re-render (for example PureComponent and ones that implement componentDidUpdate or shouldComponentUpdate and test for changes)

See https://codesandbox.io/s/zen-aryabhata-m07l4 for showcases of all issues.

So you should use

this.setState(state => ({
      myObject: {
        ...state.myObject,
        isItTrue: !state.myObject.isItTrue
      }
    }));
like image 36
Gabriele Petrioli Avatar answered Jan 23 '23 22:01

Gabriele Petrioli