首頁 >web前端 >js教程 >usePrevious 和類似的面向時間的鉤子的問題

usePrevious 和類似的面向時間的鉤子的問題

Linda Hamilton
Linda Hamilton原創
2024-12-27 18:52:17721瀏覽

The problem with usePrevious and similar time oriented hooks

Theo 本週製作了一個關於React hooks 不直觀行為的視頻,特別探索了一個名為usePrevious 的hook 的想法,以在當前渲染之前保留上次重新渲染的值版本一。一種對新舊狀態進行邏輯處理的方法。

如果您想了解如何實現它的想法,請查看視頻,在這篇文章中,我們的想法是探索像 usePrevious 這樣的鉤子的概念方面。

反應式表達

如你所見,我們在 React 中沒有這樣的原始鉤子。在 hooks 之前,在基於類別的時代,我們有一個名為 componentDidUpdate 的生命週期方法,我們將之前的所有狀態和 props 作為參數,為什麼他們不使用 hooks 來保留這種行為?

如果您正在閱讀本系列文章,可能會有點重複,但在這種情況下,我們需要討論範式轉移。

對於類,當某些狀態更新時,您沒有自動重新計算派生值的方法。如果你正在使用一些特定的 props 和 state 來計算一些新的值,你需要自己驗證其中一些是否發生了變化。

這樣,解決方案是在所有更新中呼叫回調,並將先前的值傳送給使用者。應用程式程式碼檢查差異並使用新結果更新計算狀態。這就是基於類別的元件的直接性,你完全控制資料的流向,並且需要手動控制計算。

我們來看看反應表達式。

您不必檢查並進行更改,而是編寫一個表達式、計算公式之類的。此計算需要使用目前狀態版本執行,而無需存取前一個狀態。

想像一個公式:

a = b + c


b = 10
c = 20


a = 10 + 20
a = 30

如果我使用這個表達式 100 萬次,將 b 作為 10 傳遞,將 c 作為 20 傳遞,我將得到相同的結果。這是純粹的計算。 React 執行相同的原理。所有推導的計算都應該是純粹的。

但是為什麼它很重要?

在重新渲染中做出反應。每個週期都會產生 UI 的描述,並根據當前和下一週期之間的差異,將變更提交到 DOM。每個渲染都與上一個或下一個完全分離。

UI = fn(state)

因此,對於每個不同的狀態版本,我們都有不同的 UI 版本。如果我們在這裡添加以前的值,這會變得非常混亂。因為現在它不僅取決於狀態,還取決於之前的狀態。我可以擁有多個來源,也許更複雜的表達式來處理這些來源,並且結果是不一致且不可預測的 UI,而不是只有一個來源、一個表達式和一個結果。

每個渲染都會根據先前的狀態表現不同。由於 usePrevious 的一些可能實作依賴於 React 中的時間順序,這變得更加危險。

借助並發功能,React 可以在不警告渲染的情況下停止,以優先考慮其他操作。根據 useEffect 和 ref 可以讓您保留「上一個」渲染的過時版本,甚至是真正的上一個渲染。更多混亂需要推理。

記憶化

用這樣的表達方式思考

a = b + c


b = 10
c = 20


a = 10 + 20
a = 30

其中一部分是優先順序的,需要先計算一下,我們用javascript程式碼來思考一下:

UI = fn(state)

所以現在我們有兩個獨立的表達式,可以單獨計算,而且是完全純淨的。但如果b的值變化很大,cdResult的計算成本很高,我們該如何解決呢?牢牢記住!

a = b + (c - d)

現在如果 c 或 d 發生變化,cdResult 將被重新計算。

但是在上面的文字中我說沒有先前的值,但是一個渲染的計算如何可以在下一個渲染中使用?這不會破壞計算的純粹性嗎?

事實上,沒有。例如:

const cdResult = c - d;
const a = b + cdResult;

假設我們處於渲染編號 1 中。 c 的值為 30,d 的值為 20,因此結果是 10。但是當我記住它時,React 將追蹤我添加的依賴項數組。如果其中一些發生變化,則會重新計算。

const cdResult = React.useMemo(() => c - d, [c, d]);
const a = b + cdResult;

但他們沒有改變。如果我再次呼叫這個表達式,c 為 30,d 為 20,我將得到相同的 10 作為結果。即使我處於渲染編號 2 中且其他變數發生了變化,但我在本次計算中使用的依賴項並沒有改變。

我可以在每次渲染中再次計算它,這是React的預設行為,但我可以選擇跳過不必要的重新計算,這將返回相同的值,所以我保留了它。我們保持了純度並保持了渲染之間的分離

之前的狀態

但是有一個很好的地方可以對先前的狀態、使用者操作進行邏輯處理。當然,在呼叫回調的那一刻,這將是當前狀態。但如果你有一些狀態需要根據某種邏輯進行更改,那就是這個地方。

當然,它可能有非常特殊的情況,您可能需要一個鉤子,例如 usePrevious,但要注意它可能導致的不一致,並嘗試添加保證以避免應用程式上的錯誤。

更重要的是,如果可能的話,避免它。

以上是usePrevious 和類似的面向時間的鉤子的問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn