简体   繁体   English

正确使用 setState 方法

[英]use setState method correctly

I'm new to React, I was told by a book that it is incorrect to use setState method as the example below:我是 React 的新手,有一本书告诉我使用 setState 方法是不正确的,如下例所示:

...
constructor(props) {
   super(props);
   this.state = {
       counter: 0,
          hasButtonBeenClicked: false
   }
}

render() {
 return (
 <button onClick={ this.handleClick }>
    Click
 </button>
 )
}

handleClick = () => {
   this.setState({ counter: this.state.counter + 1 });
   this.setState({ hasButtonBeenClicked: this.state.counter > 0 });
 }
...

becuase React performs changes to state data asynchronously and may choose to group together several updates to improve performance.因为 React 异步执行对 state 数据的更改,并且可以选择将多个更新组合在一起以提高性能。

I get the point, but since React performs changes asynchronously.我明白了,但由于 React 异步执行更改。 there could be times and chances that the first setState method will get called first before the second setState method, it is just a matter of probability.第一个 setState 方法可能会在第二个 setState 方法之前首先被调用,这只是概率问题。 But no matter how many times I tried, the second setState method always get called first, why?但是无论我尝试了多少次,第二个 setState 方法总是首先被调用,为什么?

Despite the fact that they're performed asynchronously, you're unlikely to see variance when testing from the same browser, and / or on the same hardware.尽管它们是异步执行的,但在同一浏览器和/或同一硬件上进行测试时,您不太可能看到差异。 Different browsers optimise instruction sets in slightly different ways, which is your best bet for examining performance (and why testing on all major desktop browsers is still recommended despite commercially Chrome often being "good enough").不同的浏览器以略微不同的方式优化指令集,这是检查性能的最佳选择(以及为什么仍然建议在所有主要桌面浏览器上进行测试,尽管商业上的 Chrome 通常“足够好”)。

The best way to do this - assuming you want them to fire in a specific order - is to chain the setState call as follows:执行此操作的最佳方法 - 假设您希望它们以特定顺序触发 - 将setState调用链接如下:

handleClick = () => {
    this.setState({ counter: this.state.counter + 1 }, () => {
        this.setState({ hasButtonBeenClicked: this.state.counter > 0 })
    });
}

But I would recommend a different design regardless - tying the hasButtonBeenClicked logic to the counter is going to introduce problems down the line.但无论如何我都会推荐一种不同的设计 - 将hasButtonBeenClicked逻辑绑定到计数器会引入问题。

  1. Don't reference this.state .不要引用this.state Use callback variant of setState , get current state from there.使用setState的回调变体,从那里获取当前的 state。 That'll explicitly guard you against the "changed the state, but the state hasn't changed yet" situations.这将明确保护您免受“更改了 state,但 state 尚未更改”的情况。

And 2. Simply put those two updates into one run of setState : 2. 只需将这两个更新放入一次setState运行中:

this.setState((prevState) => ({
    counter: prevState.counter + 1,
    hasButtonBeenClicked: prevState.counter + 1 > 0 }));

If you have lots of states to update at once, group them all within the same setState :如果您有很多状态要一次更新,请将它们全部分组到同一个setState中:

Instead of:代替:

this.setState({foo: "one"}, () => {
    this.setState({bar: "two"});
});

Just do this:只需这样做:

this.setState({
    foo: "one",
    bar: "two"
});

Or in your case:或者在你的情况下:

handleClick = () => {
   this.setState({ 
   counter: this.state.counter + 1,
   hasButtonBeenClicked: this.state.counter > 0 
   });
}

You are right, React performs changes to state data asynchronously to improve performance.你是对的,React 异步执行对 state 数据的更改以提高性能。 In your case, you should write code like this:在您的情况下,您应该编写如下代码:

handleClick = () => {
  const counter = this.state.counter + 1;
  this.setState({
    counter: counter,
    hasButtonBeenClicked: counter > 0
  });
}

Or, you can use callback parameter of setState.或者,您可以使用 setState 的回调参数。

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

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