54
29

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 の ref, useRef, forwardRefの基本的な知識

Last updated at Posted at 2022-07-18

はじめに

あやふやな理解だったので、勉強がてらのメモです。

refとは

refはコンポーネントの描画結果であるDOMノードへの参照を保持するオブジェクトです。

refを使うには、Reactの提供するHooksであるuseRefを関数コンポーネント内で呼ぶ必要があります。

refオブジェクトはcurrentというプロパティを持っています。useRefに渡した引数がcurrentプロパティの初期値になります。引数を渡さなかった場合の初期値はundefinedです。

currentは、自由に書き換え可能です(ミュータブル)。また、変更しても再レンダリングされません。この点(ミュータブルな値を抱えること)は、Reactの思想(宣言的UI)と違ってしまうと感じます。公式見解も「Don’t Overuse Refs」(使いすぎないでください)とあります。

しかし、アクセシビリティの向上を実現する手段としてのユースケースはあるので、使い所だなと感じました。

ユースケース

仕事で実際に使用したのは、オートフォーカスくらいです。他にもいくつかあるみたいです。1

forwardRefとは

forwardRefはコンポーネント内のDOMにRefオブジェクトを渡すための機能のことです。

refは特殊な属性らしく、propsとして渡したり、受け取ったりができません。

そもそも関数コンポーネントにrefを渡すことはできません。

そこで、forwardRefの登場です。forwardRefを用いれば、関数コンポーネントに対して ref が使えるようになります。

子コンポーネント(CustomInput)のテキストインプットを外からフォーカスできるようにしたい場合。

App.jsx
import React, { useRef, forwardRef } from "react";

const CustomInput = (props, ref) => {
  return <input type="text" {...props} ref={ref} />;
};

const WrappedCustomInput = forwardRef(CustomInput);

export const App = () => {
  const ref = useRef();

  const onClick = () => {
    ref.current.focus();
  };

  return (
    <>
      <WrappedCustomInput ref={ref} />
      <button type="button" onClick={onClick}>
        focus
      </button>
    </>
  );
};

関数コンポーネントに対してrefを使う場合、fowardRefでコンポーネントをラップすることでコンポーネント内のDOMにrefを渡すことができました。

9cf63ca000afbad6110bd36a1d417c1a.gif

公式はあまり推奨していなさそうだけど、アクセシビリティの手段や、いざという時のための手段として覚えておきます。

参考

  1. ユースケースを見ると、アニメーションの発火にも利用されるけど、具体的な書き方がわからなかったので教えて欲しい。:pray_tone2:

54
29
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
54
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?