[ReactDoc] useRef, Refs and the DOM
資料來源:
- Refs and the Dom @ React Docs
- Referencing Values with Refs @ React Docs beta
- Manipulating the DOM with Refs @ React Docs beta
重要觀念
ref 主要有兩個用途:
-
用來保存 DOM 節點,例如,用來控制元素的 focus, text selection 或 media 播放事件;或與第三方的 DOM 套件整合
-
用來保存不需要觸發 re-render 的資料,例如 timeout IDs、DOM 等等。
在 React 中,每次更新都包含兩個階段
- rendering:React 透過呼叫元件(functional component)來理解有哪些東西應該要呈現在畫面上
- commit:實際將變更套用到 DOM 上
普遍來說,不要在 rendering 的時候嘗試讀取或寫入 ref.current:
- 在第一次 render 時,因為 DOM nodes 還沒被建立,因此
ref.current會是null,而元件在更新時,DOM nodes 也還沒被更新完成 - React 會在 commit 階段才來設定
ref.current;在更新 DOM 之前,React 則是會先將受影響的ref.current設為null。
提示
不要在 rendering 的時候嘗試讀取或寫入 ref.current,如果有資料是需要在 rendering 是被使用,請使用 state。(除了有些時候會使用 if(!ref.current) ref.current = new Thing() 這個情況例外)。
基本使用:useRef
一般來說,因為 function component 中並沒有 this 實例,因此通常是無法使用 ref 的,例如:
// https://react.dev/learn/manipulating-the-dom-with-refs#example-focusing-a-text-input
import { useRef } from 'react';
export default function Form() {
// STEP 1:使用 useRef 來建立 inputRef
const inputRef = useRef<HTMLInputElement>(null);
function handleClick() {
// STEP 3:即可在 inputRef.current 中取得並使用該 DOM element
inputRef.current?.focus();
}
return (
<>
{/* STEP 2:將 inputRef 帶入 DOM 的 ref 屬性中 */}
<input ref={inputRef} />
<button type="button" onClick={handleClick}>
Focus the input
</button>
</>
);
}
使用 ref Callback
keywords: ref callback, useCallback with ref
有些時候 ref 對象的數量或內容是動態的,沒辦法預先就定義好,這時候可以「將『函式』帶入 <div ref="" /> 的屬性中」,這種方式稱作 "ref callback"。
React 會透過此 ref callback 將 DOM node 設定到 useRef 的 ref 中,並在元件不存在時將此 ref 的值設為 null。如此,後續開發者便可以使用 array 或 Map 的方式將此 DOM 節點保存下來做後續使用。