Jeff的隨手筆記

學習當一個前端工程師

0%

『Day 24』useRef:React 中的逃生艙

前言

在開發 React 專案的過程中,總會遇到一些特殊情況,需要存放一些不會影響畫面渲染的值,或是需要直接操作 DOM 元素。這時候,useState 好像不太適合,但 React 早就為我們準備好了另一個好用的工具:useRef。

今天就來跟大家分享一下我在使用 useRef 的心得,聊聊它的特性以及使用時機。

useRef 的基本概念

useRef 是 React 提供的一個特殊 Hook,最大的特點就是:當我們修改它的值時,不會觸發重新渲染。它就像是一個「記事本」,讓我們可以記住一些資訊,但不會影響到畫面的更新。

基本使用方式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Timer() {
const countRef = useRef(0);

function handleClick() {
// 透過 .current 存取或修改值
countRef.current = countRef.current + 1;
console.log('目前計數:', countRef.current);
}

return (
<button onClick={handleClick}>
增加計數(但不會更新畫面)
</button>
);
}

useRef vs useState

這兩個 Hook 雖然都能儲存值,但使用場景完全不同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Component() {
// useState:值改變會觸發重新渲染
const [count, setCount] = useState(0);

// useRef:值改變不會觸發重新渲染
const countRef = useRef(0);

return (
<div>
<p>State 值:{count}</p>
<p>Ref 值:{countRef.current}</p>
</div>
);
}

主要差異在於:

  • useState 的值改變會觸發重新渲染,且需要透過 setter 函式更新
  • useRef 的值可以直接修改,改變時不會觸發重新渲染

useRef 的使用時機

在實務開發中,我最常用 useRef 來處理這些情況:

  1. 儲存計時器 ID

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function AutoCounter() {
    const timerRef = useRef(null);

    useEffect(() => {
    timerRef.current = setInterval(() => {
    // 做一些事
    }, 1000);

    return () => clearInterval(timerRef.current);
    }, []);

    return <div>自動計數中...</div>;
    }

  2. 操作 DOM 元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function VideoPlayer() {
    const videoRef = useRef(null);

    function handlePlay() {
    videoRef.current.play();
    }

    return (
    <>
    <video ref={videoRef} src="video.mp4" />
    <button onClick={handlePlay}>播放</button>
    </>
    );
    }

  3. 儲存不需要渲染的資料

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function Form() {
    const prevInputRef = useRef('');

    function handleSubmit(e) {
    const currentInput = e.target.value;
    if (currentInput !== prevInputRef.current) {
    // 做一些事
    }
    prevInputRef.current = currentInput;
    }

    return <input onChange={handleSubmit} />;
    }

使用時的注意事項

雖然 useRef 很好用,但也要注意一些重點:

  1. 避免在渲染期間讀取或修改 ref 值
  2. 不要過度依賴 useRef,它主要是用來處理特殊情況
  3. 如果資料會影響畫面顯示,應該使用 useState

總結

useRef 就像是 React 提供給我們的一個「逃生艙」,當我們需要處理一些不影響渲染的值,或是需要直接操作 DOM 元素時,它就是最好的選擇。不過記得要適時使用,不要為了避免重新渲染而濫用它喔!