KAKUTA TECH BLOG

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 で保持する理由として正しいものはどれですか?