簡體   English   中英

調用 setState 后 React 如何分離舊狀態和新狀態?

[英]How does React separate old and new state after setState has been called?

創建組件時,定義了this.state 然后,在調用 setState 之后,React 以某種方式將舊狀態和新狀態拆分為兩個對象。 例如使用鈎子 shouldComponentUpdate 我們可以像這樣區分這兩個狀態:

shouldComponentUpdate(nextProps, nextState) {
    return (this.state.foo != nextState.foo);
}

我從 github 下載了 React 源代碼,並找到了調用這些函數的位置,但很快就很難跟蹤正在發生的事情。 我從來沒有發現這種分裂(或者他們如何實現這種行為)發生的地方。 我確實發現 React 可以/可以使用淺比較來區分狀態,所以我想知道他們是否只是簡單地克隆狀態對象,然后將更新的值合並到其中一個中,以便稍后可以比較它們中的兩個。 這樣對嗎? 在這種情況下,嵌套結構如何處理? 或者他們是否使用 get/set 版本和/或代理 API 版本以某種方式捕獲更改?

在使用shouldComponentUpdate類概念的shouldComponentUpdate JS 中,如果我們不覆蓋它, Component將始終返回 true 並且PureComponent實現淺比較(淺比較通過檢查兩個值是否相等來工作,例如字符串、數字和 in在 object 的情況下,它只檢查props 和 state 上的引用),如果任何 props 或 state 發生變化,則返回 true。

如果我們覆蓋了 shouldComponentUpdate,我們將擁有之前的 props 和之前的狀態。 對象類組件中已經存在存儲。 對於下一個道具和下一個狀態,我認為:

  • 接下來的道具將傳遞給組件。 所以,它是新的。
  • 下一個狀態在函數setState上處理。 它是從以前的狀態克隆的,並為此添加了新的更改。 所以,前一個狀態的引用和下一個狀態的引用總是不同的。

供將來參考:我設法在 React 源代碼中找到了新狀態與舊狀態不同的位置。

為此,我使用了 React Github 存儲庫的最新主分支(commit hash e7b255341b059b4e2a109847395d0d0ba2633999 )。

免責聲明,這只是我的解釋,我主要憑記憶。 神奇的事情發生在文件packages/react-reconciler/src/ReactUpdateQueue.new.js 中,在函數getStateFromUpdate 中 調用setState 時,會創建一個更新對象 (update.tag = UpdateState) 並將其添加到更新隊列中(用於異步行為)。 該標簽用於此函數的 switch 語句中,用於特定的更新邏輯。 在案例 UpdateState 的底部,我們看到React 克隆了之前的狀態並將其與“partialState”合並,這是傳遞給setState調用的狀態對象。 此克隆是使用以下方法完成的:

// Merge the partial state and the previous state.
return Object.assign({}, prevState, partialState);

新狀態從這個函數返回,之前的狀態仍然存儲在某個地方。 它們現在可以用於以后的比較。 作為旁注,這里也處理 ForceUpdate,它只返回先前的狀態(然后根據相同的邏輯成為新狀態)。

關於我的問題的第二部分,如何處理嵌套結構。 鑒於這些新發現的知識,經過一番搜索后,我發現這個問題很好地回答了這個問題

暫無
暫無

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

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