剛開始時,usestate 及其所有怪癖可能會讓人不知所措。現在將 useref 加入其中,您的大腦就會爆炸。
我認為更深入地研究 useRef 與 useState 的技術細節會很有幫助,因為工程師通常很難理解它們之間的差異以及何時選擇其中一個。
這是我對每一個的定義,粗略且明顯過于簡單化:
useState 是一個鉤子,可讓您訪問和更新值,從而觸發重新渲染。
useRef 是一個鉤子,可以讓你引用渲染不需要的值。
您可能會問自己,為什么了解這些內容帶來的好處很重要?好吧,您可能會想將 useState 應用于所有內容,僅僅因為它確實有效。
是的,但是,您的應用程序變得越復雜,組件將狀態屬性向下傳遞 5 個級別,并在此過程中觸發一堆不必要的更新,您可能會比您想象的更早開始遇到性能問題。
許多開發人員的另一個誤解是認為 useRef 只能操作和訪問 DOM 元素,這很遺憾,因為你們都錯過了 useRef 可以做的其他 99 件事。
讓我們從 useState 開始吧!現在請豎起耳朵,我親愛的開發者 ?????
? 使用狀態
useState 是一種強大但簡單的方法,可以在變量值發生變化時更新視圖,它使最新值與屏幕保持同步,而無需我們手動執行任何操作。聲明語法如下 const [memesILiked, setMemesILiked] = useState(9000).
現在,讓我們討論一下當您使用 useState 執行操作時會發生什么。
更新狀態值會觸發重新渲染,正如您可能想象的那樣,重新渲染視圖對于瀏覽器來說是一個非常昂貴的操作。以下是 React 和瀏覽器如何結合運行以確保您的應用程序得到更新:
- 事件觸發器:事件觸發狀態更新。單擊、計時器或其他任何東西。
State Update:調用 setState 并安排組件的更新,該組件被標記為“臟”(需要重新渲染)。
協調階段:React 開始新虛擬 DOM 和舊虛擬 DOM 之間的協調。它遞歸地重新渲染組件及其所有子組件。
檢查差異:React 將新的虛擬 DOM 樹與之前的虛擬 DOM 樹進行比較。更改存儲在要應用于真實 DOM 的更新列表中。
渲染階段:使用新狀態調用渲染方法或函數組件。
提交階段:React 將 diff 過程中的更改應用到真實 DOM。
更新 DOM:更新真實的 DOM 以反映新狀態。瀏覽器重新繪制 DOM,視覺上更新 UI。
渲染后效果:調用組件重新渲染后計劃運行的任何效果。這包括使用渲染期間更改的依賴項注冊的 useEffect 掛鉤。
唷
,這有很多東西……雖然上述過程確保您的 UI 與應用程序狀態保持同步,但它也強調了為什么過多或不必要的重新渲染會導致性能問題。幸運的是,React 提供了多種策略和工具來幫助優化此過程,例如 useMemo 和 useCallback,但這超出了本文的范圍!
總而言之,useState 是一個非常方便的 hook,如果使用得當,它可以為用戶提供很好的體驗。以主題切換為例。借助 useState,您可以輕松地在淺色和深色模式之間切換,讓您的用戶立即滿意地看到應用程序根據他們的喜好進行轉換。
?
useRef
現在,我們來談談 useRef。 useState 的作用是在狀態改變時觸發重新渲染,而 useRef 就像一個安靜的觀察者,永遠不想引起別人的注意。它非常適合存儲可變值,這些值更改時不需要重新渲染。語法看起來像 const memeRef = useRef(null).
useRef 最常用于直接訪問 DOM 元素。例如,如果您需要以編程方式聚焦輸入字段,則 useRef 可以保存對該元素的引用。但 useRef 的功能不僅僅限于 DOM 訪問。它還可以存儲
任何
可變值!我的朋友們,這就是神奇發生的地方???(無論如何在我看來)。
這樣想:useRef 是一種在渲染過程中
持久保存值
而不觸發重新渲染的方法。這使得它非常適合存儲計時器、計數器甚至組件的先前狀態等數據。與 useState 不同,更新 ref 不會通知 React 重新渲染您的組件。它只是靜靜地更新價值并繼續其業務。
這是一個實際的例子:假設您想要實現一個簡單的計數器,但您不希望每次增加計數器時 UI 都會更新。您可以使用 useRef 來存儲計數器值。計數器會按預期增加,但由于組件不關心此引用值以進行渲染,因此不會發生重新渲染。
useRef 在保留狀態的最新值而不引起額外渲染方面也很有用。例如,如果您使用
interval
來更新值,但您不希望該值每毫秒觸發一次重新渲染,則 useRef 是您的首選工具。它允許值在后臺更改,保持 UI 響應并避免不必要的重新渲染。
總而言之,useRef 最適合用于:
訪問 DOM 元素:經典用例,例如聚焦輸入字段。
存儲可變值:不需要重新渲染,例如計時器或之前的值。
跨渲染保持值:不會導致重新渲染,保持 UI 流暢高效。
既然您
希望
理解了其中的區別(如果我正確地履行了我的職責),那么讓我們深入研究一些不那么常見的用例。我將更多地關注 useRef ,因為我覺得它是這里的無名英雄。
-
跟蹤組件掛載狀態
:useRef 可用于跟蹤組件是否掛載或卸載,這對于避免卸載后狀態更新很有用。
保存靜態值
:對于存儲在渲染之間不會更改的靜態值(例如常量或緩存值),useRef 比 useState 更有效。
防止重新初始化
:如果你想阻止一段代碼重新運行每個渲染(例如,初始化WebSocket連接)。
存儲之前的回調
:如果需要保留之前的回調函數的引用,useRef 可以存儲之前的函數引用,而不影響組件的渲染周期。
引用計時器 ID
:使用計時器(如 setTimeout 或 setInterval)時,將計時器 ID 存儲在 useRef 中,以避免每次設置或清除計時器時觸發重新渲染。
觸發動畫
:對于強制觸發動畫(如 CSS 過渡或滾動動畫),useRef 可用于直接與 DOM 元素交互,而不會導致重新渲染。
?
結論
雖然 useState 對于管理和響應應觸發重新渲染的狀態更改至關重要,但 useRef 是一個沉默的伙伴,可以幫助您在不中斷 UI 的情況下管理狀態。
知道何時使用它們可以幫助您避免潛在的性能問題,并使您的 React 應用程序更加高效和可維護!
感謝您的閱讀,如果您成功了,請舉起爪子,擊掌五! ???( ?????)???
腳注:
1 明顯夸張了。
2 我有點戲劇化,以防你看不出來。