なぜ「バケツリレー」ができないの? `forwardRef` が解決するReactのちょっとした意地悪
Reactを学び始めたばかりの皆さん、こんにちは。コンポーネントを組み合わせて画面を作る楽しさを味わい始めた頃でしょうか?
Reactで開発をしていると、ふとこんな場面に出くわします。「親コンポーネントから、子コンポーネントの中にある特定のボタンを、直接『カチッ』と操作(フォーカス)させたい!」
普通に `ref` を渡せばいいんじゃないの? と思うかもしれませんが、ここでReactの「ちょっとした意地悪」にぶつかります。実は、ただのpropsとして `ref` を渡そうとしても、Reactは「えっ、`ref` って何のこと?」と無視してしまう仕様になっているんです。
今日は、その壁を軽やかに飛び越えるための魔法の杖、`forwardRef` についてお話しします。
—
「配送業者」としての `forwardRef`
まず、身近な例え話で考えてみましょう。あなたは大きなマンション(親コンポーネント)の管理人に、大切な小包(`ref`)を託しました。
「これ、このマンションの302号室(子コンポーネントの中のDOM要素)に届けて!」
しかし、マンションの管理人は非常に厳格です。「私はあくまで『マンション全体』の受付係であって、中の特定の部屋まで小包を運ぶ役割は持っていないんだ」と突っ返されてしまいます。
そこで登場するのが `forwardRef`(Refの転送) です。
これを使うと、管理人に「この小包は302号室宛てだから、中まで運んでね」という特別な通行許可証を持たせることができます。これが `forwardRef` の正体です。
—
実践:ボタンをフォーカスさせる仕組み
では、実際のコードで見てみましょう。下の例は、「親がボタンを押すと、子コンポーネントの中にある入力欄にフォーカスする」というものです。
import React, { useRef, forwardRef } from ‘react’;
// 子コンポーネント:forwardRefで包んで「refを受け取れる」ように改造します
const MyInput = forwardRef((props, ref) => {
// ここで渡されたrefを、実際のinput要素に紐付けます
return ;
});
// 親コンポーネント
export default function App() {
const inputRef = useRef(null);
const handleClick = () => {
// ボタンを押すと、子コンポーネントのinputにフォーカス!
inputRef.current.focus();
};
return (
);
}
ここがポイント!
1. `forwardRef` で囲む: 子コンポーネントを関数で囲うだけでなく、`forwardRef` という特殊な関数でラップします。
2. 第2引数に `ref`: 通常の `props` に加えて、第2引数として `ref` を受け取れるようになります。
3. DOMに繋ぐ: 受け取った `ref` を、ターゲットとなるDOM(ここでは ``)の `ref` 属性にセットするだけ。
これだけで、親は「子の中身」を直接操作できるようになるのです。
—
「コンポーネントの独立性」という考え方
「でも、わざわざこんなことしなくても、親から直接操作しちゃえばいいのでは?」と思うかもしれません。確かにその通りですが、Reactの設計思想では「コンポーネントは独立して動くべき」と考えます。
例えば、ボタンの見た目を共通化して「誰でも使い回せる部品」を作ったとき、その部品を使う人が「中のボタンがどうなっているか」をいちいち知らなくて済むようにしたいですよね。
`forwardRef` は、「内部構造を隠蔽しながら、どうしても必要な時だけ外部からの操作を許可する」という、非常に上品でプロフェッショナルなインターフェースを提供してくれるんです。
—
つまずきやすいポイントへのフォロー
もし、あなたがこのコードを書いてみて動かなかったとしても、全く落ち込む必要はありません。私も初心者の頃は、`ref` が `undefined` になっていて、何時間も悩んだ経験があります。
- 「`forwardRef` を書き忘れていませんか?」: これが一番多いミスです。`ref` は単なるpropsではない、ということを思い出してくださいね。
- 「子コンポーネントが関数コンポーネントですか?」: `forwardRef` は主に、関数コンポーネントで使われます。
最後に
`forwardRef` は、いわば「親子の絆を深めるための特別なパイプライン」です。使いすぎるとコンポーネント同士がガチガチに結びつきすぎてしまうので、本当に必要な時だけ使うのがコツです。
「DOMを直接触らなきゃいけないけど、コンポーネントの綺麗さも保ちたい」。そんな現場のジレンマを解決するこの手法、ぜひ皆さんのプロジェクトでも試してみてください。
迷ったり、分からなくなったりしたら、いつでもまたここに戻ってきてくださいね。Reactの旅は、一歩ずつ進めば必ず景色が開けてきますよ。応援しています!

コメント