[英]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.