27
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React で ref をどう扱うかを整理する

27
Posted at

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 の保持あたりから使い慣れていくのがよいと思います。

参考

27
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?