简体   繁体   中英

How can mutating `this.state` and then immediately calling `setState` break?

It's said that React components' states should be treated as if they are immutable, and that mutating this.state can be error-prone even if you immediately call setState . That is,

// #1: bad...
this.state.items.push("New item");
this.setState({items: this.state.items});

// #2: good...
this.setState({items: this.state.items.concat(["New item"])});

Can someone elaborate on what exactly would cause the first version above to fail?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM