useRef 是什麼?
在 React 函式元件中,useRef
是一個用來建立「參考物件」的 Hook。這個參考物件可以用來:
-
取得 DOM 元素的參考,方便我們直接操作該元素,例如聚焦(focus)、捲動(scroll)等。
-
儲存不會觸發重新渲染的資料,像是變數狀態的快照、計時器 ID 或其他需要跨渲染周期保持的值。
useRef
回傳一個物件,這個物件的 .current
屬性會保存你想記錄的資料。當 .current
改變時,React 不會重新執行元件的 render。
useRef 實務案例整合示範
下面我用一個範例示範兩個常見的 useRef
用法:
-
操作 DOM 聚焦 input
-
儲存並顯示上一個狀態值
import React, { useState, useRef, useEffect } from "react";
function UseRefExample() {
// 狀態:計數器
const [count, setCount] = useState(0);
// useRef:取得 input 元素的參考
const inputRef = useRef < HTMLInputElement > null;
// useRef:儲存上一個 count 的值(不會觸發重新渲染)
const prevCountRef = (useRef < number) | (null > null);
// 每次 count 改變時,把當前 count 存入 prevCountRef
useEffect(() => {
prevCountRef.current = count;
}, [count]);
// 點按按鈕時,讓 input 聚焦
const handleFocusInput = () => {
inputRef.current?.focus();
};
return (
<div style={{ padding: "20px" }}>
<div>
<input
ref={inputRef}
type="text"
placeholder="請點擊按鈕自動聚焦"
style={{
padding: "8px",
marginRight: "10px",
border: "1px solid #ccc",
}}
/>
<button onClick={handleFocusInput} style={{ padding: "8px 12px" }}>
聚焦輸入框
</button>
</div>
<div style={{ marginTop: "20px" }}>
<p>目前計數器:{count}</p>
<p>
上一個計數器:
{prevCountRef.current !== null ? prevCountRef.current : "無"}
</p>
<button
onClick={() => setCount(count + 1)}
style={{ padding: "8px 12px" }}
>
計數加一
</button>
</div>
</div>
);
}
export default UseRefExample;
程式碼說明:
-
取得 DOM 元素參考:
inputRef
使用useRef(null)
建立,並綁定到<input>
元素上。
呼叫inputRef.current?.focus()
時,瀏覽器就會把游標聚焦到該輸入框。 -
儲存前一次狀態值:
prevCountRef
是另一個useRef
,用來儲存上一次的count
。
利用useEffect
監聽count
變化,把當前值存進prevCountRef.current
。
這樣就可以在畫面上同時顯示目前和前一次的計數,但不會因為存前一次值而觸發重渲染。
什麼時候會用到 useRef?
-
操作原生 DOM: 例如自動聚焦 input、滾動到指定位置、播放影片、操控第三方元件。
-
跨渲染保持資料: 有些資料不適合放在 state,避免重新渲染,但又要在不同函式間共用,比如計時器 ID、前一個狀態、旗標(flag)等。
-
避免在 callback 中捕捉舊狀態: 用
useRef
可即時存取最新資料,避免閉包問題。