Ref、useRefについて

■まずはRefについて

Refとは、renderメソッドで作成されたDOMノードもしくはReact要素の参照を保持するオブジェクトであり、Refオブジェクトのcurrent属性を参照することでノードにアクセスできる。

Refを利用するユースケースは以下。

  • フォーカス、テキストの選択およびメディアの再生の管理
  • アニメーションの発火
  • サードパーティーのDOMライブラリとの統合

■useRefについて

useRefとはRefオブジェクトを生成するフックである。

useRef(initialValue)で初期値がinitialValueのミュータブルなRefオブジェクトを生成する。

なお、「ミュータブル(mutable)なデータ」とは、一度作成した後も値が変更できる、という性質を持つデータのことを言う。

■useRefの挙動(TypeScript編)

App.tsx

import { useRef } from "react";

export default function App() {
  const ref = useRef();
  console.log(ref);

  return (
    <div className="App">
      <h1>Refのテスト</h1>
      <div ref={ref}>テストdiv</div>
    </div>
  );
}

としたとする。

しかし、これでは、エラーになる。

useRefには「初期値」と、さらに、TypeScript環境においては「生成したRefオブジェクトと、参照したいDOMのrefの型が一致している」、つまり

const ref = useRef<HTMLDivElement>(null);

としてやらなければならない。

つまり、全体として

import { useRef } from "react";

export default function App() {
  const ref = useRef<HTMLDivElement>(null);
  console.log(ref);

  return (
    <div className="App">
      <h1>Refのテスト</h1>
      <div ref={ref}>テストdiv</div>
    </div>
  );
}

のようにすることで、初めてrefを参照することができる。

ここでの、console.logでの結果として

  1. {current: null}
  2. {current: HTMLDivElement}

と出てくる。

このことは、Reactコンポーネントにおいて、1度目のプリレンダリングでは初期値のnullが入ってきて、jsxに辿り着いて、参照したいDOMのref属性のcurrentが参照できて、変化が起きたRefオブジェクトによってconsole.logが評価された、という流れになると思われる。