Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS: Why shouldn't I mutate nested state?

Tags:

reactjs

I've read the ReactJS documentation about setState. Specifically, this line:

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

But in my code, I do things like this:

var x = this.state.x;
x.y.z.push("foo"); // z is a list
this.setState({x:x});

This code seems to work and update state correctly. But according to the documentation, I'm breaking the rules. What's the problem with this approach? Are there performance issues? Race conditions? Will I be scolded by the Facebook dev team? Ideally, I'd like to avoid the immutability helpers and all the other craziness and keep things simple.

like image 889
mathew Avatar asked Feb 10 '23 06:02

mathew


1 Answers

By manipulating state directly, you are circumventing React's state management, which really works against the React paradigm. The most significant benefit of React's setState is that it immediately triggers a re-render, which merges your DOM changes from the shadow DOM into the document DOM. So, you capture all the state changes you need in some handler, then build up the state changes you want in a literal object, then pass that to setState. This is not quite what your example above does.

So while the code sample you provided technically breaks this rule, since you are calling setState directly after mutating through a reference to a state object property, your changes are immediately being funneled through React's state management. So, everything will work as you expect. The idea is that you don't want to get in the habit of making many changes to state in this way, it's better to capture your intended state in a new literal object or array, then set it to the state once (i.e., with no previous mutations of state) through a call to setState, which will trigger a single re-render.

EDIT: To more definitively answer your question, I would add that the real concern is that a dev would directly manipulate state in many different places or methods, without calling setState, and then at some later point or other code, call setState and then wonder why their render isn't producing the results they expected. Since setState does an object merge between the known, managed state, and the literal object passed as an argument to setState, it's possible the results would not be what you would expect if you had previously manipulated state directly.

like image 169
stolli Avatar answered Feb 27 '23 10:02

stolli