接下來幾篇文章將會針對 React 常見的 Hooks 的使用目的與場景 ,內容主要都是透過官方文件、一些大師影片以及自身開發經驗彙整出來的,如果有很不錯的學習資源我也會在文末留下來源供大家參考喔!
首篇就來一個最近開發中很常使用到的 useRef
認識一下吧 useRef
先讓我們來看看 React 官方文件的 useRef 定義:
useRef
is a React Hook that lets you reference a value that’s not needed for rendering.
簡單來說有與 state
相似的功能都是暫存值,但最大的不同就是 useRef
裡的 ref object 就算變動了也不會造成畫面的 re-render,是完全隔絕於 component life cycle 外的狀態。
useRef 實用場景
1. Referencing a value with a ref(使用 ref 對照值)
這是 useRef
最基本的用法。可以用它來創建一個「可變」的 ref object,object 的 .current
屬性被初始化為傳遞給 useRef()
的參數,在後續的 re-render 中,useRef
將返回相同的 object。而且這個 object 可以更改其 current
屬性以存儲為新的值,就算值更新了也不會讓整個畫面 re-render。
接著舉兩個常見的使用案例:
🔎 ex1. 存取最新的值
若我們想要在若干秒數後取得某一個狀態的最新值,useRef
就可以派上用場了!!
1 | const [timeoutCount, setTimeoutCount] = useState(0); |
這邊為什麼使用 ref.current
存值,而不是用 state
?
因為當 setTimeout
被建立時,它使用的是當時 count
的值,它依賴一個閉包(closure)來異步訪問 count
。因此當組件重新渲染時,一個新的閉包會被創建,但這不會改變最初被封閉的值,所以如果用了 state
,當 5 秒後你以為 count
已經變更了拿出來用,會發現該 state
還是初始的 0。
這就是 useRef
的一個實用情景可以避免上述的情形發生,我們透過將狀態值與 ref 的 current
屬性同步,並在 timeout
中讀取 current
以取得我們想要的值。
🔎 ex2. 存取「前一個值」
呈上,我們當然也可以拿來存取前一個值。
1 | const [name, setName] = useState(''); |
2. Manipulating the DOM with a ref(使用 ref 操作 DOM )
在 React 中我們可以使用 useRef
來直接操作 DOM 元素。通過將 ref 對象的 .current
屬性設置為一個 DOM 節點,可以直接讀取或修改這個節點。
🔎 ex1. 取用某一個 DOM 作進一步操作
最簡單常用的使用情境包含列印、操作特定的 DOM Scroll to view、監聽無限滾動的最後一個元素等等,這邊舉列印為例:
1 | const printRef = useRef<HTMLDivElement>(null); |
🔎 ex2. 父組件使用 useRef
調用子組件的方法
在 react 的父子層的關係,父層若要呼叫存在子層的函式通常會將函式放置在父層,並且將函式與相關的狀態一起傳入子層中做使用。也是之前分享過的文章【圖解】React 常見的父子傳值方法 Props(https://leewanhsuan.github.io/2022/04/25/01-props/)所提過的方法。
而下方改成以 useRef
的方式實踐,這段範例中使用 React.forwardRef
和 React.useImperativeHandle
來從父組件調用子組件的方法,這樣可以把方法保留在子層中,卻又能在父層中調用。
1 | import React, { useRef, useEffect } from 'react'; |
3. Avoiding recreating the ref contents(避免不必要的重建 ref 內容)
使用 useRef
可以幫助你避免在重新渲染 component 時不必要地重建 ref 的內容,因為 ref 會在 re-render 中保持不變,例如一些資源很大的影音 component 就可以使用此方法,避免重複拿取資源、更新畫面。
1 | const Video = () => { |
以上就是 useRef
官方提供的三種使用情境以及對應的範例,在整理的過程中也讓我更加認識 useRef
了,希望也能幫助到你唷!
最後,請注意 useRef 使用事項
Web Dev Simplified 的講者在其 useRef
教學影片中特別強調,雖然 useRef 有多種用途,但它並不應該過度取代 useState
。特別是在處理用戶交互,如值的更改(onChange Value)時,過度依賴 useRef
可能會讓程式碼變得過於複雜。也可能讓你失去 React Hook 的渲染生命週期(re-render life cycle)所帶來的優勢。
💬 參考資料: