Assuming i have a Counter component and it renders a button that you could click to increment its count:
class Counter extends Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
inc = () => {
// Directly mutate state and setState({})
this.state.count += 1
this.setState({})
}
render() {
return (
<button onClick={this.inc}>{this.state.count}</button>
)
}
}
In the inc method, instead of doing
setState(prevState => ({ count: prevState.count + 1 }))
i directly mutated the state, and given an empty object to setState function. I clearly know this is not a recommended pattern, but just curious why this example would work and seems no bugs at all. I clicked the button and it updates the count successfully.
What do those two lines do under the hood, and Do they actually equal the official recommended way of setState?
>Solution :
Why directly mutate react state and setState({}) aftewards successfully update and renders the component […]
Calling the setState function asks react to rerender the component, and this.setState({}) says to rerender and change no state values. Even though you’ve told react to change no values, it still renders by default, and when it does it uses whatever values happen to be in state. And since you’ve mutated the state, the state happens to have a new value.
[…] without bugs?
It only seems bug free because you’ve got a simple example. The bugs will show up when you need to do anything with the previous state. For example, if you add in a shouldComponentUpdate, the previous state will always equal the current state:
shouldComponentUpdate(prevProps, prevState) {
console.log(prevState.count, this.state.count);
return prevState.count !== this.state.count;
}