First of all, I know there's a similar question but its accepted answer does not actually answer the question, so I am asking it again.
It is well known that we should not mutate the state directly, because of many issues that can happen. I personally always make a copy of the data I will update, mutate this copy, and assign it to the original variable in the state with a call to setState
, which is the common and canonical way of updating the state:
let copy = JSON.parse(JSON.stringify(this.state.someDeepObject))
copy.a.b.c = 5
this.setState({ someDeepObject: copy })
However a colleague of mine uses an alternative way of updating the state. He mutates the state directly, and then uses the updated value in the state to update the state with setState
, enabling a re-render and preventing all problem that a direct mutation would normally cause:
this.state.someDeepObject.a.b.c = 5
this.setState({ someDeepObject: this.state.someDeepObject })
Since he calls setState
right after mutating the state, this way of mutating the state, although tricky and not quite reliable, works, and has never bugged anywhere it is used in the application, as far as I know.
It is not the canonical way of mutating the state, however, it works. I would use the canonical way instead, but my colleague is a pragmatic man and, if it works and is reliable (which his code seems to be), he won't change it.
A more complete example of the situation will show you that his code does work:
class Button extends React.Component {
constructor() {
super();
this.state = {
count: 0,
};
}
updateCount() {
this.setState((prevState, props) => {
return { count: prevState.count + 1 }
});
}
updateCountDirectly() {
this.state.count = this.state.count + 1
}
updateCountDirectlyButSafely() {
this.state.count = this.state.count + 1
this.setState({ count: this.state.count })
}
render() {
return (
<div>
<button onClick={() => this.updateCount()} >
Clicked {this.state.count} times (normal)
</button>
<button onClick={() => this.updateCountDirectly()} >
Clicked {this.state.count} times (directly)
</button>
<button onClick={() => this.updateCountDirectlyButSafely()} >
Clicked {this.state.count} times (directly but safely)
</button>
</div>
);
}
}
React.render(<Button />, document.getElementById('app'));
(copy paste this in CodePen to test it)
Will his code cause any problem?
I won't use it myself but, if it doesn't actually cause any problem, then I won't bother him with it anymore.