簡體   English   中英

react setState 回調沒有更新狀態

[英]react setState callback doesn't have the updated state

如果monthOffset = 12條件將評估為真,如果yearOffset = 2018則將yearOffset狀態更新為 2017。 根據我閱讀的反應文檔和其他答案, 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")
}

也許您可以通過以下方式簡化邏輯,以避免多次調用setState可能導致意外結果:

handleClick(e) {

  const { monthOffset, yearOffset } = this.state

  // call setState once
  this.setState({ 

    // Always decrement month offset
    monthOffset : monthOffset - 1, 

    // Only decrement year offset if current month offset === 12
    yearOffset : (monthOffset === 12) ? yearOffset - 1 : yearOffset

  }, () => {

    console.log("state updated to", this.state)
  })

  console.log("clicked")
}

文檔說回調總是有效的,但我從經驗中知道它並不總是返回你所期望的。 我認為這與在狀態本身內部使用可變對象有關。

文檔: 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()的函數中擁有它的副本,或者你應該從componentDidUpdate獲取nextState


事后思考:作為參數傳遞給setState()的任何內容都是通過引用(而不是通過值)傳遞的。 因此,如果您的狀態中有一個對象SearchFilters: {} ,並且在您對setState()的調用中,您有

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

您可能已將SearchFilters設置為DEFAULT_SEARCH_FILTERS以清除名為“搜索過濾器”的表單,但您將有效地將DEFAULT_SEARCH_FILTERS (常量)設置為SearchFilters ,清除您的DEFAULT_SEARCH_FILTERS

預期的行為? 你告訴我。

在 React 中調用setState有兩種流行的模式:對象setState“功能setState 函數式 setState 通常setState調用中調用當前狀態(或“先前狀態”,或任何您想調用的舊狀態)時使用。 這樣做是因為setState是異步的,因此后續的setStates有時可以在 React 成功完成第一個setState循環之前運行。

您在setState調用中使用了現有狀態,因此它是使用功能性setState的合適位置。 代替

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

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

如果你和我一樣,當我第一次看到這個時,你可能會想,“嗯?這和我有什么不同?” 不同之處在於,當setState被傳遞給函數而不是對象時,它會將更新排隊而不是通過通常的解析過程,從而確保事情按順序完成。

或者你可能不這么想; 您實際上在第二次setState調用中使用了功能性setState 在你的第一個中使用它也將確保事情正確排隊。

發生這種情況是因為您使用的是從前一個狀態(在this.setState yearOffset
您應該直接從回調中讀取狀態,如下所示:

() => console.log("yearOffset", this.state.yearOffset)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM