javascript - React 中的 setState() 未更新 onClick 状态

标签 javascript reactjs react-redux

我正在构建一个组件,用于呈现按周分组的 Redux 存储中的数据。由于星期仅与此组件相关,因此我将其值存储为本地状态,如下所示:

  constructor(props) {
    super(props);
    this.state = {
      page: 0,
      week: this.getWeekNumber(new Date())[1],
      year: this.getWeekNumber(new Date())[0]
    };
  }

这通常是我在组件中所做的事情,并且这种方法从未遇到过任何问题。我有三个按钮,可以根据周重新呈现数据:

...
render() {
...
       <Button onClick={() => this.handleRenderWeek("previous")}>
          Previous Week
        </Button>
        <Button onClick={() => this.handleRenderWeek("current")}>
          Current Week
        </Button>
        <Button onClick={() => this.handleRenderWeek("next")}>Next Week</Button>
...

处理渲染的辅助函数定义如下:

  handleRenderWeek = action => {
    const { week, year, page } = this.state;
    switch (action) {
      case "previous":
        this.setState({
          page: 0,
          week: week - 1,
          year
        });
        break;
      case "current":
        this.setState({
          page: 0,
          week: this.getWeekNumber(new Date())[1],
          year: this.getWeekNumber(new Date())[0]
        });
        break;
      case "next":
        this.setState(prevState => ({ week: prevState.week + 1 }));
        break;
      default:
        this.setState({
          page: 0,
          week: this.getWeekNumber(new Date())[1],
          year: this.getWeekNumber(new Date())[0]
        });
        break;
    }
    this.props.fetchCalendarsAndBookings(week, year, page);
  };

问题是,当我单击下周按钮时,状态保持不变。仅当我第二次单击时它才会增加。当我第三次、第四次等等时,它继续正确地递增。

当我点击当前周上周按钮时,按照上述操作,我遇到了完全相同的事情:首先单击状态保持不变(因此发送具有先前状态的 API 调用),然后它开始在第二次点击之后开始工作。

经过一番研究,我发现 setState() 是异步调用的,因此我将上面的代码替换为让 setState() 引用其之前的状态,如下所示:

this.setState((prevState, props) => {
            return {
              week: prevState.week + 1
            };
          }); 

但是这并没有解决问题,我仍然遇到同样的问题。我做错了什么?

最佳答案

经过几个小时的调查,我设法找到了问题的根本原因。显然,发生的情况是 setState() 更新 week 状态较晚。该 API 正在使用旧版本的状态进行调用。

为了解决这个问题,我使用了async/await:

  1. 首先更新状态并等待
  2. 然后调用 API 获取结果。

代码现在看起来像这样:

  handleRenderWeek = async action => {
    switch (action) {
      case "previous":
        await this.decrementWeek();
        break;
      case "current":
        await this.resetWeek();
        break;
      case "next":
        await this.incrementWeek();
        break;
      default:
        await this.resetWeek();
        break;
    }
    console.log("Updated State: ", this.state.week);
    await this.props.fetchCalendarsAndBookings(
      this.state.week,
      this.state.year,
      this.state.page
    );
  };

这里的主要教训有两个:

  1. setState() 是一个异步函数。大宇。
  2. setState() 与 redux thunk 和其他复杂的异步函数混合时,始终使用 then() 将它们相应地链接起来,甚至更简单,使用 async/await 语法。

关于javascript - React 中的 setState() 未更新 onClick 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50049690/

相关文章:

javascript - 从数组中选择特定数字

reactjs - 将字符串渲染为 React 组件

reactjs - 如何将 redux 存储中的状态重置为初始状态?

reactjs - 将状态作为 props 从父级传递给子级,然后从子级 onSubmit 更新父级

reactjs - 如何测试解决 promise 然后在 React 中更改状态的方法?

reactjs - React-Testing-Library - 使用 Redux 和 Router 包装组件

javascript - React、Redux 和 three.js 的性能问题

javascript - 如何在JavaScript中转换日期格式?

javascript - 从外部检测 iframe 内的点击?

javascript - 服务器发送事件 - 事件流 - 触发 PHP 服务器端事件?