反应setState回调没有更新的状态

时间:2018-08-22 01:01:38

标签: javascript reactjs setstate

如果monthOffset = 12,则条件将为true,如果yearOffset,则将yearOffset = 2018状态更新为2017。根据我已经阅读的react docs和其他答案,this.setState中的回调函数会在状态更新后触发,但console.log()仍会输出2018。我尝试了几种方法基于其他相关问题的答案实施此代码的方法,但是我的方法不起作用。我不确定为什么。

handleClick(e) {
  const { monthOffset, yearOffset } = this.state
  this.setState({ monthOffset: monthOffset - 1 })
  if ( monthOffset - 1 === 11 ) { this.setState((prevState) => { 
    return { yearOffset: prevState.yearOffset - 1 } },
    () => {console.log("yearOffset", yearOffset)}
  )}
  console.log("clicked")
}

3 个答案:

答案 0 :(得分:4)

也许您可以通过以下方式简化逻辑,以避免多次调用<tr *ngFor="let number of [0,1,2,3,4]">{{number}}</tr> 可能导致意外结果:

setState

答案 1 :(得分:2)

文档说,回调始终有效,但是根据经验,它并不总是返回您所期望的结果。我认为这与在状态本身内部使用可变对象有关。

文档:https://reactjs.org/docs/react-component.html#setstate

您不能完全依赖回调。相反,您可以做的就是创建

var stateObject = this.state

对对象进行任何必要的更改:

stateObject.monthOffset -= 1

然后设置如下状态:

this.setState(stateObject);

这样,您就可以在nextState中拥有stateObject的副本

要澄清:要在设置状态之前进行所有评估,所以请这样做:

monthOffset -= 1

然后if (monthOffset === 12) yearOffset -=1;

然后var stateObj = {monthOffset: monthOffset, yearOffset: yearOffset}

然后this.setState(stateObj);


  

从文档中:“ setState()的第二个参数是可选的回调函数,将在setState完成并重新呈现组件后执行。通常,我们建议改将componentDidUpdate()用于此类逻辑。

因此,基本上,如果您想获取下一个状态,则应该在调用setState()的函数中包含该状态的副本,或者应该从nextState获取componentDidUpdate


后续考虑:作为参数传递给setState()的所有内容均通过引用传递(而不是通过值传递)。因此,如果您在状态内以及在对SearchFilters: {}的调用中有一个对象setState(),则您有

setState({SearchFilters: DEFAULT_SEARCH_FILTERS}); // do not do this

您可能已将SearchFilters设置为DEFAULT_SEARCH_FILTERS,以清除名为“搜索过滤器”的表单,但是实际上,您将DEFAULT_SEARCH_FILTERS(常数)设置为{ {1}},清除您的SearchFilters

  

预期的行为?你告诉我。

答案 2 :(得分:1)

在React中调用setState有两种流行的模式:对象setState"functional setState"Functional setState is generally used when the current state(或“先前状态”,或您想称其为旧状态的任何内容)is invoked in the setState call.之所以这样做是因为setState是异步的,因此后续的setStates可以有时会在React无法完成第一个setState周期之前运行。

您在setState调用中使用了现有状态,因此使用功能setState是一个合适的地方。替换

this.setState({ monthOffset: monthOffset - 1 })

使用

this.setState(monthOffset => {return {monthOffset: monthOffset - 1}})

如果当我初次看到它时像我一样,您可能会想:“嗯?这与我有什么不同?”区别在于,当setState传递给函数而不是对象时,它会将更新放入队列中,而不是通过通常的解析过程进行处理,从而确保事情按顺序进行。

或者您可能不会这样想;您实际上在第二个setState调用中使用了功能setState。在您的第一个中也使用它,可以确保一切正确排队。