It is said that we should never mutate this.state
, but I think it means "never mutate this.state
directly but always use this.setState()
to mutate it instead.
But what if we mutate it directly but also follow it by a this.setState()
?
The following code actually works. Why is the number updated on screen (even componentDidUpdate()
is invoked) -- is it by luck and should not be depended on?
Does the line
this.setState({ numbers: this.state.numbers })
actually tells React that numbers
is modified and therefore, check for any updated value? Or is React supposed to ignore it, because if React takes it as numbers
referring to itself, it means nothing has changed. There is no key
in the list items, so I think the default is the index of entry is used as keys. So the keys didn't change, meaning the list items haven't changed, and why is the list updated on screen?
To just update an array element, it seems so complicated. There seems to be two acceptable methods:
- Immutability Helpers
this.setState({ numbers: newNumbersArray })
Is there any official docs that describe how to get it done, instead of blog posts or a Stack Overflow question that is full of different opinions? In Vue.js, it seems all it takes is numbers.splice()
to replace an array element and that's it.
With this.state
followed by a this.setState()
, and with absence of key
, can we count on it working?
class App extends React.Component {
state = {
numbers: [2, 4, 6]
};
clickHandler() {
this.state.numbers[1] = Math.random();
this.setState({ numbers: this.state.numbers });
}
componentDidUpdate() {
console.log("In componentDidUpdate()");
}
render() {
return (
<div>
<ul>{this.state.numbers.map(a => <li>{a}</li>)}</ul>
<button onClick={this.clickHandler.bind(this)}>Click Me</button>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>