プログラミングのゴミ箱

日々の学習の中で知らなかったことについて、調べたことを解説します。

React.forwardRefってなんだろう、、、

React.forwardRefってなんだろうって公式ドキュメントを見てみると、なんかいまいちわからなかったので解説しちゃうよ。
ref のフォワーディング – React

そもそもRefって何?

RefというのはDOMの要素を取得するためのプロパティです。ちょっと何言ってるかわからないと思うので例を挙げて説明します。

import { useRef, useEffect } from 'react';

function App() {
  const ref = useRef(null);
  useEffect(() => {
    console.log(ref.current);
  }, []);
  return (
    <>
      <div ref={ref}>hello world</div>
    </>
  );
}

export default App;

プログラムの説明をします。
まず、ReactのuseRefを使ってrefという変数を定義します。useRefはRefを使いたいときに使用します。
そして、useEffectを使って初回レンダリング時のみrefの値を出力します。

f:id:chanichiwasshoi:20211226160452p:plain
ref result

すると、上のようなDOMの値が返って来ます。このように、refを使うことでDOMを直接操作できるようになります。

f:id:chanichiwasshoi:20211226161242p:plain
ref

これがrefの役割です。

forwardRef

では、本題のforwardRefに入ります。
結論を言うと、React.forwardRefは自分で作ったコンポーネントにrefを渡せないという問題を解決するためのメソッドです。
なぜ自分で作ったコンポーネントにrefが渡せないのか、以下の例を見てください。

const MyTag = ({ title, ref }) => {
  return <div ref={ref}>{title}</div>;
};

function App() {
  const ref = useRef(null);
  return (
    <>
      <MyTag ref={ref} title="ikko" />
    </>
  );
}

これを実行しても「`ref` is not a prop」と怒られてしまいます。ブラウザ側から見ると、このrefはMyTagを参照したいのかMyTagの中のdivを参照したいのか判別できないため、自作のコンポーネントにrefを渡すのは禁止されているのです。
でも、どうしても呼び出し先の要素を参照したい。そんなときに登場するのがforwardRefです。
forwardRefは以下のように書きます。

const MyTag = React.forwardRef((props, ref) => (
  <div ref={ref}>{props.title}</div>
));
function App() {
  const ref = useRef(null);
  return (
    <>
      <MyTag ref={ref} title="ikko" />
    </>
  );
}

forwardRefを使用することで明確に呼び出し先の要素を参照するということがわかるようになり、その要素をref変数に渡せます。

f:id:chanichiwasshoi:20211226163659p:plain
forwardRef 実行