2
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?

More than 1 year has passed since last update.

React のフックで最初につまづいたのが useRef でした(そして今なおつまずき続けています)。なんとなく DOM 操作したときに使ったような…くらいのイメージしかないので、今回は気合を入れて useRef について調べていきます。

▼ React の基本を復習したい方はこちらもご覧ください

useRef とは

公式ドキュメント を参考にすると、ref を使うケースとしては

  1. コンポーネントに何か値を記憶させたい
  2. だけど記憶させている値が変化しても再レンダリングを起こしたくない(無限ループになってしまう場合など)

という場面です。1 は state でも実現できますが、2 は state だとできません。state を変更するためには state setter function が必要であり、state setter function の実行をトリガーとして React は再レンダリングを行うためです。

▼ state についてはこちらもご覧ください

ref.current の形で current というオブジェクトを使うことができます。

import { useRef } from 'react';

export default function Counter() {
  let ref = useRef(0);

  function handleClick() {
    ref.current = ref.current + 1;
    alert('You clicked ' + ref.current + ' times!');
  }

  return (
    <button onClick={handleClick}>
      Click me!
    </button>
  );
}

current は読み取りと書き込みが可能です。書き込み可能ということは state setter function のような特別な関数は必要ありません。
またReact からは追跡されません = レンダリングは起こりません。

state と ref の使い分け、ref を使うタイミング

大きな性質の違いはレンダリングの有無です。
つまり state は画面上に表示されており画面上で更新されてほしい値、ref は画面上で更新の必要がない値に使うのがいいでしょう。

また DOM 操作で使うことも多いでしょう。

DOM 操作における useRef の使い方

React ビルトインで入っていない動作を行わせる場合は ref が必要になってくることがあります。
ここでは 公式ドキュメント から一例を引用します。

import { useRef } from 'react';

export default function Form() {
  const inputRef = useRef(null);

  function handleClick() {
    inputRef.current.focus();
  }

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Focus the input
      </button>
    </>
  );
}

// 引用: https://beta.reactjs.org/learn/manipulating-the-dom-with-refs

公式ドキュメント で実際に試してみてほしいのですが、ボタンを押すと input タグがフォーカスされるようになっています。

最初 inputRef.current に代入されているのは null です。
React が jsx をもとに input タグを作成したとき、 input に対する参照が inputRef.current に入ります

よってイベントハンドラ関数 handleClick の内部に書かれている処理 inputRef.current.focus()input.focus() となります。よって無関係のボタンから input を操作することができるのです。

実装したことがある例として、私は確か「ボタンを押すと input タグに働きかけて画像をアップロードできるようにする」という操作で ref を使いました。このケースとよく似ていますね。

まとめ

  • refstate と同じように、レンダリングされても消えないように値を記憶することができる
  • ref に保存した値が変更されたことによるレンダリングは起こらない
  • ref.current の形で current というオブジェクトを使うことができ、ここに保存されたデータの読み取りと書き込みができる
  • 値は保存したいがレンダリングには影響させたくない場合や、無関係の要素にアクセスする DOM 操作を行う場合に有用

参考資料

2
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
2
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?