When you call setState
with a new value, some components within React can compare the new state to the previous state to detect changes for performance enhancement (see here: https://facebook.github.io/react/docs/advanced-performance.html). The method is called shouldComponentUpdate
, and receives the next props and state for comparison. Some frameworks like Omniscient and Om use this.
In your first example you've mutated the state already (objects and arrays are by-reference in JS), and so calling setState may be a no-op (as the state is already the same). Your component might not automatically re-render.
Here's an example:
// Let's assume that `this.state === {numbers: [1]};` at the start
this.state.numbers.push(2);
// Oops - we just changed this.state directly,
// so now this.state === `{numbers: [1, 2]}`
// Now, react might compare the old this.state (which has been modified to [1, 2])
// to the object you're passing in (which is also [1, 2]).
// This might be a no-op.
this.setState({numbers: this.state.numbers});
In the second example MDN says that "The concat() method returns a new array comprised...", that is — you're not modifying the original, you're returning a new array entirely. In the first example, .push edits the existing array.
Because it's a new array the comparison will always run as expected.