【React】でDOMを直接操作するuseRefの使い方とrefとstateの違い

2022年12月2日React

ReactでDOMを直接操作するuseRefの使い方を紹介します。

useRefの使いどころ

useRefをいつ使うかですが、DOMのメソッドを使いたいときです。
たとえば、よくあるユースケースとしては、input要素にフォーカスを当てたいときやblur()でフォーカスを取り除きたいときなど、DOM要素のメソッドはプロパティを使いたいときに使用します。
あとは、動画の再生、停止をボタンクリックで操作したいときにも、videoタグのpauseイベントで停止、playイベントで再生という操作をする必要があるので、useRefを使用します。

ReactでDOMを直接操作するuseRefの使い方

ref属性でuseRefの変数を渡すと、currentというプロパティがあり、currentプロパティに対して値を保持できる仕組みになっています。
useRefは、再レンダリングを発生させずに、値を保持する方法です。
stateでは、再レンダリングが発生するのでコンポーネントに保持している値は破棄されてしまいますが、
useRefを使うと、たとえ再レンダリングしてもcurrenctプロパティに値を保持したままにすることが可能です。

useRefを変数に格納すると、refオブジェクトを返します。
そのオブジェクトには、currentプロパティがあり、そこに値を設定します。
ref.currentで値にアクセスすることができます。
その値は読み書きどちらもすることが可能です。

refとstateの違い

再レンダリング後に値が保持できるかどうか

refは、再レンダリングされても情報が保持できます。
stateでは、レンダリングされると初期化されます。

値変更に伴って再レンダリングが発生するかどうか

refの値を変更しても再レンダリングが発生しません。
stateは変更されると、再レンダリングが発生します。

DOMを直接操作するかどうか

refオブジェクトをJSXのref属性にわたすと、そのDOMにアクセスできるようになります。
注意点としては、refの値を変更しても再レンダリングが発生しないという点で、
refの値自体は変更されていても、再レンダリングが発生しないため、コンポーネントが更新されず、画面の表示上の見た目も変化しない点です。
値は変わっても見た目が変わらないので注意が必要です。

useRefの例

import { useState, useRef } from "react";

const FocusInput = () => {
  const [value, setValue] = useState("");
  const inputRef = useRef();
  return (
    <div>
      <h3>離れた要素を直接操作</h3>
      <input type="text" ref={inputRef} value={value} onChange={(e) => setValue(e.target.value)} />
      <p>適当なDOM</p>
      <button onClick={() => inputRef.current.focus()}>
        フォーカス
      </button>
    </div>
  );
};

const Sample = () => {
  return (
    <>
      <FocusInput />
    </>
  );
};

export default Sample;

インポート

import { useState, useRef } from "react";

まずは、reactからuseRefをインポートします。

変数を作成

const inputRef = useRef();

そして、useRefを変数に持ちます。

ref属性にセット

      <input type="text" ref={inputRef} value={value} onChange={(e) => setValue(e.target.value)} />

そして、ref属性にその変数を渡します。

JSXで使う

      <button onClick={() => inputRef.current.focus()}>
        フォーカス
      </button>

そうすることで、ref属性に指定したDOM要素のメソッドなどを使用することができるようになります。
上の場合だと、currentというプロパティがあり、そこにinputが指定できているので、inputのプロパティなどにアクセスすることができます。

currentを経由して、focus()メソッドを使用することができます。

React

Posted by devsakaso