Javascript setState()在单击时处于React not updating状态

Javascript setState()在单击时处于React not updating状态,javascript,reactjs,react-redux,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] }; } handl

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

  constructor(props) {
    super(props);
    this.state = {
      page: 0,
      week: this.getWeekNumber(new Date())[1],
      year: this.getWeekNumber(new Date())[0]
    };
  }
  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);
  };
this.setState((prevState, props) => {
            return {
              week: prevState.week + 1
            };
          }); 
这通常是我在我的组件中所做的,并且这种方法从来没有任何问题。我有三个按钮将根据周重新呈现数据:

...
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>
...
问题是,当我单击
nextweek
按钮时,
week
状态保持不变。它仅在我再次单击时递增。当我第三次、第四次等时,它继续正确地递增

当我点击
本周
前一周
按钮时,我经历了完全相同的事情:首先点击状态保持不变(因此发送一个带有前一状态的API调用),然后在第二次点击之后开始工作

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

  constructor(props) {
    super(props);
    this.state = {
      page: 0,
      week: this.getWeekNumber(new Date())[1],
      year: this.getWeekNumber(new Date())[0]
    };
  }
  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);
  };
this.setState((prevState, props) => {
            return {
              week: prevState.week + 1
            };
          }); 

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

下面代码段中的“下一步”按钮按预期工作。其他按钮由于未定义的过程而失败。我尽可能地把它和你的代码保持在一起。我不认为您的问题包含在您在问题中提供的代码中

类Hello扩展了React.Component{
建造师(道具){
超级(道具);
此.state={
第周:0
};
}
handleRenderWeek(行动){
const{week,year,page}=this.state;
开关(动作){
“以前”一案:
这是我的国家({
页码:0,
周:第1周,
年
});
打破
案例“当前”:
这是我的国家({
页码:0,
周:this.getWeekNumber(新日期())[1],
年份:this.getWeekNumber(新日期())[0]
});
打破
案例“下一个”:
this.setState(prevState=>({week:prevState.week+1}));
打破
违约:
这是我的国家({
页码:0,
周:this.getWeekNumber(新日期())[1],
年份:this.getWeekNumber(新日期())[0]
});
打破
}
}
render(){
返回(
你好{this.props.name},周是{this.state.week}
此.handleRenderWeek(“先前”)}>
前一周
this.handleRenderWeek(“当前”)}>
本周
本.handleRenderWeek(“下一周”)}>下周
);
}
}
ReactDOM.render(
,
document.getElementById('容器')
);

经过数小时的调查,我终于找到了问题的根本原因。显然发生的情况是,
setState()
更新
状态的时间晚了。正在使用旧版本的状态调用API

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

  • 首先更新状态并等待
  • 然后调用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
        );
      };
    
    这里的主要教训有两个:

  • setState()
    是一个异步函数。大宇
  • setState()
    与redux thunks和其他复杂的异步函数混合使用时,始终使用
    then()
    或更简单的
    async/await
    语法相应地链接它们

  • 我隐约记得这与标记为已处理的单击事件有关,但我不确定。初始状态
    week
    prop是否正确?
    handleRenderWeek
    是在
    render()
    之前还是之后声明的?@IvanBurnaev你是什么意思?@DJ。宣布哪一个地方没有区别