Blog Article
React の useRef とは何か? 「再レンダーしない値」の正体

useRef とは何か?state との違いを理解する
はじめに
React を学んでいると、useState や useEffect と並んで useRef という Hook を目にします。しかし、useRef は初見では役割が非常にわかりにくく、「いつ使うのか」「何のためにあるのか」が掴みにくい Hook です。
useState は「画面を更新するための値」、useEffect は「副作用を扱うための仕組み」と比較的わかりやすいですが、useRef は「値を保持する」と説明されても、state と何が違うのかがはっきりしません。
この記事では、useRef の本質を初学者にも理解できるように、なぜ必要なのか、いつ使うのか、これがないとどう困るのか、そして実際のコードを通して丁寧に解説します。
参考にしたリンク
useRef とは何か?
useRef を一言で言うなら、再レンダーを発生させずに値を保持できる入れ物です。
React のコンポーネントは、state が変わると再レンダーされます。しかし、すべての値の変更が画面更新につながるわけではありません。値が変わっても UI を更新する必要がない場合、その値を state で管理する必要はありません。
そこで登場するのが useRef です。useRef は値を保持できますが、その値を変更しても再レンダーは起きません。
この特徴こそが useRef が存在する理由です。
なぜ state ではなく useRef が必要なのか
React の設計思想は、「UI は state の結果である」という考え方です。そのため、変更されたときに UI を更新したい値は state で管理します。
しかし、アプリには次のような値も存在します。
- 前回の値を覚えておきたい
- タイマー ID を保存したい
- DOM 要素に直接アクセスしたい
- スクロール位置を保持したい
これらのように、値が変わっても UI を更新する必要がないものがあります。このような値を state にすると、値が変わるたびに再レンダーが発生するため、不要な再レンダーにつながる可能性があります。
useRef は、このような「変更されても再レンダーを発生させずに保持したい値」を扱うために使われます。
useRef がないとどう困るか
useRef がなければ、開発者はこれらの値を別の方法で管理する必要があります。
useRef を使えば、コンポーネントの再レンダーをまたいで値を保持しながら、その値を変更しても再レンダーを発生させないようにできます。
そのため、React のコンポーネント内で「値を保持したいが、その変更によって UI を更新する必要はない」という場合に useRef が役立ちます。
useRef の基本的な使い方
useRef は次のように使います。
const ref = useRef(初期値)
この ref は、次のような構造を持っています。
{
current: 初期値
}
値は ref.current に保存されます。
ref.current = 新しい値
この代入をしても、コンポーネントは再レンダーされません。ここが state との決定的な違いです。
useRef はなぜ再レンダーしないのか
React は state の変更によって再レンダーしますが、useRef で取得した ref オブジェクトの current を変更しても、React の再レンダーは発生しません。
React は ref.current の変更によってコンポーネントを再レンダーしないため、値が変わっても画面は更新されません。
これは欠点ではなく、useRef の最大の特徴です。
useRef と useState の違いを理解する
useState は、値が変わったときに UI を更新するために使います。
一方、useRef は、値が変わっても UI を更新する必要がない場合に使います。
例えばカウンターを作る場合、state を使います。
const [count, setCount] = useState(0)
count が変わると画面が更新される必要があるからです。
一方で、クリック回数を裏で記録するだけなら、useRef で十分です。
const clickCount = useRef(0)
function handleClick() {
clickCount.current++
}
この値は増え続けますが、画面は更新されません。
DOM に直接アクセスするための useRef
useRef の代表的な使い方が、DOM 要素への直接アクセスです。
React は基本的に DOM を直接触ることを推奨していませんが、フォーカスを当てる、スクロールするなどの操作は必要になります。
const inputRef = useRef(null)
useEffect(() => {
inputRef.current.focus()
}, [])
return <input ref={inputRef} />
このように、ref を JSX の ref 属性に渡すことで、実際の DOM 要素にアクセスできます。
これは useRef の非常に重要な役割です。
前回の値を保持する useRef
useRef は、前回の値を覚えておく用途にもよく使われます。
const prevCount = useRef(0)
useEffect(() => {
prevCount.current = count
}, [count])
これにより、「前回の count」を保持できます。
state でも前回の値を保持することはできますが、UI の更新を必要としない値を保持する場合は useRef が適しています。
タイマーや ID を保持する useRef
setInterval や setTimeout の ID を保持する場合も useRef が使われます。
const timerRef = useRef(null)
function startTimer() {
timerRef.current = setInterval(() => {
console.log("tick")
}, 1000)
}
function stopTimer() {
clearInterval(timerRef.current)
}
この ID は、変更されても UI を更新する必要がないため、useRef で管理できます。
まとめ
useRef とは、再レンダーを発生させずに値を保持できる仕組みです。
React において、すべての値を state で管理する必要はありません。値が変わったときに UI を更新する必要がある値は useState、更新する必要がない値は useRef を使うというように、目的に応じて使い分けます。
ポイント整理
useRefは再レンダーを発生させずに値を保持できる- DOM へのアクセスに使う
- 前回の値やタイマー ID を保持する
useStateは UI の更新が必要な値に使うuseStateとuseRefは役割が異なる
useRef の役割を理解すると、React の設計思想がよりはっきりと見えてきます。
理解度チェック
学んだ内容を確認してみましょう。各問題の選択肢から正しい答えを選んでください。
useRef の特徴として正しいものはどれですか?
useState と useRef の使い分けとして正しいものはどれですか?
useRef の代表的な用途として、記事で説明されているものはどれですか?
タイマー ID を useRef で保持する理由として正しいものはどれですか?