简体   繁体   English

怎样使this.state突变然后立即调用setState中断?

[英]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 . 据说应该将React组件的状态视为不可变的,并且即使立即调用setStatethis.state进行this.state是容易出错的。 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 ). 当您使用新值调用setState时,React中的某些组件可以将新状态与先前状态进行比较,以检测更改以提高性能(请参见此处: https : //facebook.github.io/react/docs/advanced-performance。 html )。 The method is called shouldComponentUpdate , and receives the next props and state for comparison. 该方法称为shouldComponentUpdate ,并接收下一个shouldComponentUpdate和状态进行比较。 Some frameworks like Omniscient and Om use this. 诸如OmniscientOm之类的某些框架都使用此框架。

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). 在第一个示例中,您已经改变了状态(对象和数组在JS中是按引用的),因此调用setState可能是空操作(因为状态已经相同)。 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. 在第二个示例中,MDN表示“ concat()方法返回一个包含...的数组”,即—您没有修改原始数组,而是完全返回了一个数组。 In the first example, .push edits the existing array . 在第一个示例中,.push 编辑现有数组

Because it's a new array the comparison will always run as expected. 因为它是一个新数组,所以比较将始终按预期进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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