React を学び始めると、state はよく使う一方で、ref は少し分かりづらく感じることがあります。
この記事では、ref とは何か、state とどう違うのか、どのような場面で使うのかを整理します。
ref とは
ref は、レンダリングに直接関係しない値を保持したり、DOM 要素を直接参照したりするための仕組みです。
React では、画面に表示する値は基本的に state で管理します。
一方で、以下のようなものは ref で扱います。
- input にフォーカスを当てたい
- タイマー ID を保持したい
- 再レンダリングを発生させたくない値を持ちたい
つまり ref は、UI の表示そのものではなく、補助的に値を保持するときに使うものです。
state との違い
ref を理解するうえで一番大事なのは、state との違いです。
| state | ref | |
|---|---|---|
| 用途 | 画面表示に関わる値の管理 | DOM 参照や、再レンダリング不要な値の保持 |
| 値の更新時 | 再レンダリングされる | 再レンダリングされない |
たとえば、画面に表示するカウントの値であれば state を使うべきです。
逆に、「今動いている setTimeout の ID を保持しておきたい」といった用途なら ref が適しています。
useRef の基本的な書き方
ref は、関数コンポーネントでは useRef を使って扱います。
import { useRef } from "react";
function Sample() {
const countRef = useRef(0);
return <div>サンプル</div>;
}
useRef は、current というプロパティを持つオブジェクトを返します。
この current に値を入れて使います。
countRef.current; // 0
1. DOM 要素を参照する
ref の代表的な使い方は、DOM 要素の参照です。
たとえば、ボタンを押したときに input にフォーカスを当てたい場合です。
import { useRef } from "react";
function Sample() {
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
inputRef.current?.focus();
};
return (
<div>
<input ref={inputRef} />
<button onClick={handleClick}>フォーカスする</button>
</div>
);
}
inputRef が input 要素を参照しており、ボタンを押すと focus() が呼ばれます。
このような DOM 操作は state では表現できず、ref が適した場面です。
2. 再レンダリング不要な値を保持する
ref は、再レンダリングしなくてよい値を保持するのにも使えます。
たとえば、タイマー ID を保持したいケースです。
import { useRef } from "react";
function Sample() {
const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
const startTimer = () => {
timerRef.current = setTimeout(() => {
console.log("タイマー実行");
}, 1000);
};
const clearTimer = () => {
if (timerRef.current !== null) {
clearTimeout(timerRef.current);
}
};
return (
<div>
<button onClick={startTimer}>開始</button>
<button onClick={clearTimer}>停止</button>
</div>
);
}
タイマー ID は画面に表示する値ではないため、state に入れる必要はなく、ref で持つのが自然です。
ref を使うときの注意点
ref は便利ですが、何でも ref に入れればよいわけではありません。
画面表示に関わる値は state で管理するべきです。
以下のような値は state が適しています。
- 入力欄に表示する値
- 開閉状態
- 選択中の値
- API の取得結果を画面に出す値
これらを ref で持つと、値が変わっても再レンダリングされず、画面が更新されません。
以下の基準で切り分けるのが基本的に良さそうです。
- 表示に関わるもの → state
- 表示に関わらないもの → ref
子コンポーネントの DOM を参照する
通常、ref は DOM 要素に直接渡します。
ただし、子コンポーネント内部の DOM 要素を親から参照したいこともあります。
React 19 では、ref は通常の props として渡せます。
import { useRef } from "react";
type CustomInputProps = {
placeholder?: string;
ref?: React.Ref<HTMLInputElement>;
};
function CustomInput({ placeholder, ref }: CustomInputProps) {
return <input ref={ref} placeholder={placeholder} />;
}
function Parent() {
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
inputRef.current?.focus();
};
return (
<div>
<CustomInput ref={inputRef} placeholder="入力してください" />
<button onClick={handleClick}>フォーカスする</button>
</div>
);
}
まとめ
ref は、React における DOM 参照や、再レンダリング不要な値の保持に使う仕組みです。
state との違いはシンプルで、state は画面表示に関わる値、ref は画面表示に直接関わらない値です。
まずは input のフォーカス制御やタイマー ID の保持あたりから使い慣れていくのがよいと思います。