特性
useRef 主要有兩個特性:
- 可以操作 DOM
- 值被更新時,並不會觸發元件重新渲染:
以往 React 改變 State 時,往往會重新渲染元件,也就是將元件從頭到尾再跑一次。不過存在 useRef 裡的值就算改變,也不會觸發渲染。我們可以利用這樣的特性來阻止無限迴圈,或取得過去的值。
useRef 會回傳一個含有 current 屬性的物件。
操作 DOM
舉例來說,當我們希望元件一渲染,表單就自動 focus 在某 input ,就可以透過 useRef 。
首先,宣告變數值,並用 useRef 來初始化,在我們上面的範例中,我初始化為 null 。接下來,把 DOM 綁上 ref 。最後,因為是「一渲染就要執行某事」,所以需要用到 useEffect ,而且只執行一次,所以第二個參數放空陣列。在第一個函式中,運用 .focus() 來鎖定指定 DOM ,讓 input 一渲染,就順利被 focus 住。
阻止無限迴圈
useRef 並不會因為值被改變就重新渲染,因此當我們要做一些… 例如使用 setInterval 每隔一段時間就一直把數字加一,的這種工作時,就可以用 useRef 避免無限迴圈的問題。
在畫面上,我們讓數字每隔一秒就會加一,除非按下 stop 才會停止。若我們跳過 useRef ,直接在 useEffect 裡宣告 interval ,讓他等於 setInterval ,那在 stop 按鈕,會無法取用 interval ,因為 interval 是在 useEffect 中被宣告的,但 stop 按鈕在外面。因此必須改成用 useRef 在外面宣告。
不只如此,在 useEffect 直接放 setInterval ,並透過 setState 更新資料,會因為資料不斷改變而不斷渲染,變成無限迴圈。但利用 useRef 更新資料不更新畫面的特性,可以避免這件事發生。
先宣告 intervalRef 為 useRef ,再將他的 current 指定為 setInterval 這個函式。當按下 stop 時,則用 clearInterval 來停止函式。
取得過去的值
每次資料更新後, functional component 就會重新渲染一次,這會導致我們難以在重新渲染後,取得還沒更新前的資料。不過因為 useRef 即使更新資料,也不會造成重新渲染的緣故,讓我們得以利用它來取得前值。
首先,在畫面上我放了一個 input ,並把他綁定在 input 這個 State 上,每當內容改變時,都會透過 setInput 來更新 State 。接著,我宣告 prevInput 並綁定 useRef 來代表之前的值。每當 input 改變時,我就把 input 的內容存到 prevInput.current 當中。
如此一來,就可以透過 prevInput.current 來取得之前輸入的文字了。