はじめに
あやふやな理解だったので、勉強がてらのメモです。
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)のテキストインプットを外からフォーカスできるようにしたい場合。
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を渡すことができました。
公式はあまり推奨していなさそうだけど、アクセシビリティの手段や、いざという時のための手段として覚えておきます。
参考
-
ユースケースを見ると、アニメーションの発火にも利用されるけど、具体的な書き方がわからなかったので教えて欲しい。 ↩