在等待之后多次调用setState

时间:2018-09-24 08:22:07

标签: javascript reactjs

我已经在Codepen中写了一个测试用例

通过单击按钮运行测试,然后从浏览器控制台查看结果。

您可以从控制台日志中看到,即使我在之前 setState多次调用await,它也只会更新一次组件。

但是如果我在之后 setState多次调用await,它也会多次更新组件。

知道为什么会这样吗?

代码:

/*
 * A simple React component
 */
class Application extends React.Component {

  state = {
    value: 0
  }

  onClickHandler = (e) => {
    this.runAsyncFunc();
  }

  runAsyncFunc = async() => {
    console.log('BEFORE AWAIT');
    this.setState({ value: 1 });
    this.setState({ value: 1 });
    this.setState({ value: 1 });

    await setTimeout(()=>{}, 2000);

    console.log('AFTER AWAIT');
    this.setState({ value: 1 });
    this.setState({ value: 1 });
    this.setState({ value: 1 });
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.log('updated');
  }

  render() {
    return <div>
      <p>{this.state.value}</p>
      <button onClick={this.onClickHandler}>RUN TEST</button>
      <p>Please check from Browser Console's Log</p>
    </div>;
  }
}

/*
 * Render the above component into the div#app
 */
React.render(<Application />, document.getElementById('app'));

2 个答案:

答案 0 :(得分:2)

之所以发生这种情况,是因为当this answer states React尝试批处理setState调用并在可能的时候一起处理它们。但这不是异步计算的情况,因为React(以及一般人)无法预测和再现setState的被异步调用的顺序。

因此,在您的情况下,它会退回到仅更新3次状态。

答案 1 :(得分:1)

您可以从React.Component生命周期文档(https://reactjs.org/docs/react-component.html)中获得答案

componentDidUpdate() is invoked immediately after updating occurs. This method is not called for the initial render. React Component Lifecycle

使用此方法shouldComponentUpdate()。如果没有理由应用新的渲染,则此方法允许您的组件退出更新生命周期。开箱即用,shouldComponentUpdate()是一个无操作的返回true。这意味着每次我们在组件中启动更新时,我们都会重新渲染。

我添加了更多代码

  shouldComponentUpdate = function(nextProps, nextState) {
    return nextState.value !== this.state.value;
  }

  // Change value will set after await
  runAsyncFunc = async() => {
    console.log('BEFORE AWAIT');
    this.setState({ value: 1 });
    this.setState({ value: 1 });
    this.setState({ value: 1 });

    await setTimeout(()=>{}, 2000);

    console.log('AFTER AWAIT');
    this.setState({ value: 2 });
    this.setState({ value: 2 });
    this.setState({ value: 2 });
  }

检查我的Codepen

因此,如果您要防止不必要的渲染自定义方法shouldComponentUpdate