React only renders a component again when you call setState. If you assign to this.state or to something inside it, the screen keeps showing the old value, and the next setState may overwrite your change.
The constructor is the one place where you can assign this.state, because nothing has rendered yet.
Configure
Off by default. To turn it on:
bunfig.toml
[lint.rules]
"react/no-direct-mutation-state" = "error" # or "warn"
Examples
Reported:
class Counter extends React.Component {
increment() {
this.state.count++;
}
rename(name) {
this.state.user.name = name;
}
}
Not reported:
class Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0, user: props.user };
}
increment() {
this.setState(state => ({ count: state.count + 1 }));
}
rename(name) {
this.setState(state => ({ user: { ...state.user, name } }));
}
}
A callback in the constructor runs later, so an assignment there is reported:
class Counter extends React.Component {
constructor(props) {
super(props);
props.store.subscribe(() => {
this.state.count = props.store.count;
});
}
}