正确使用setState方法

时间:2019-10-14 10:29:12

标签: javascript reactjs setstate

我是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 });
 }
...
  

因为React异步地更改状态数据,并且可以选择将多个更新组合在一起以提高性能。

我明白了,但是由于React异步执行更改。有时,第一个setState方法将在第二个setState方法之前被首先调用的机会和机会,这只是一个概率问题。但是无论我尝试了多少次,总是总是先调用第二个setState方法,为什么?

4 个答案:

答案 0 :(得分:3)

尽管它们是异步执行的,但是在同一浏览器和/或同一硬件上进行测试时,您不太可能看到差异。不同的浏览器以稍微不同的方式优化指令集,这是检查性能的最佳选择(这也是为什么尽管商业上Chrome通常“足够好”,但仍建议在所有主流桌面浏览器上进行测试的原因)。

执行此操作的最佳方法(假设您希望它们按特定顺序触发)是按以下方式链接setState调用:

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

但是无论如何我都会建议采用另一种设计-将hasButtonBeenClicked逻辑与计数器绑定会带来问题。

答案 1 :(得分:1)

  1. 不要参考this.state。使用setState的回调变体,从那里获取当前状态。这将明确警告您避免出现“状态已更改,但状态尚未更改”的情况。

然后2.将这两个更新简单地放入setState的一次运行中:

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

答案 2 :(得分:0)

如果您要一次更新许多状态,请将它们全部分组在同一setState中:

代替:

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

只需执行以下操作:

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

或者您的情况:

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

答案 3 :(得分:0)

是的,React异步更改状态数据以提高性能。 对于您的情况,您应编写如下代码:

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

或者,您可以使用setState的回调参数。