【入門編】 forwardRefとPropsの組み合わせ – React実践ガイド

こんにちは!Reactの学習、楽しく進められていますか?
コンポーネントを組み合わせて画面を作っていく感覚は、まるでレゴブロックのようでワクワクしますよね。

でも、Reactを触り始めて少し経つと、こんな壁にぶつかることがありませんか?

「親コンポーネントから、子コンポーネントの中にある『本当のDOM(inputタグなど)』を直接操作したい!」
「フォーカスを当てたり、高さを測ったりしたいのに、普通にPropsを渡しても上手くいかない……」

そう、Reactの世界では、データは基本的に「親から子へ」一方通行で流れるルールになっています。そのため、子どもの中身(DOM)を親から触ろうとすると、ちょっとしたコツが必要になるんです。

そこで登場するのが、今日お話しする`forwardRef`(フォワード・レフ)です!
名前はちょっといかついですが、大丈夫ですよ。一つひとつ、身近な例えを交えながら優しく紐解いていきましょう。

—

1. `forwardRef`ってなに?(宅配便の「転送サービス」のイメージ)

いきなりコードを書く前に、イメージを掴みましょう。

例えば、あなたが大きな荷物(DOMへの参照 = `ref`)を、マンションの「305号室の佐藤さん」に届けたいとします。
でも、そのマンションの1階には頑丈なオートロックの受付(親コンポーネント)があって、直接305号室のドアまでは行けません。

そこで受付の人に、こう頼みますよね。
「すみません、この荷物、305号室の佐藤さん(子コンポーネントの中にあるinput要素)に転送(forward)してもらえませんか?」

この「受け取った荷物を、奥にある本当の宛先までスルーっとパスする仕組み」が、まさに `forwardRef` です。

通常、ReactのPropsとして `ref` という名前は特別な予約語のような扱いになっていて、そのままでは子コンポーネントにうまく渡せません。「おいおい、そのままじゃ渡せないよ!」とReactが怒ってしまうんです。
そこで `forwardRef` で包んであげることで、「あ、この `ref` は中身のDOMまでパスしていいやつね!」とReactに教えてあげられるわけですね。

—

2. 実際のコードを見てみよう!

百聞は一見にしかず。まずは、ボタンを押したら「カスタム入力欄」に自動でカーソルが当たる(フォーカスされる)という、よくある実用的なコンポーネントを作ってみましょう。

ここでは、今どきのReact(TypeScript)で現場でもバリバリ使われている書き方でご紹介しますね。

import React, { useRef, forwardRef } from ‘react’;

// ① 子コンポーネントのPropsの型定義です
// 今回は特に特別なPropsはないので空っぽですが、将来的にここに独自のPropsを追加できます
type CustomInputProps = {};

// ② forwardRefを使って、親から受け取ったrefを内部のinput要素に「転送」します
// の順番で、[DOMの型, Propsの型] を指定するのがお約束です!
const CustomInput = forwardRef((props, ref) => {
return (


{/ 親から受け取った ref を、そのまま生粋の input タグにバトンタッチします /}

);
});

// ③ 親コンポーネント側から使ってみましょう
export default function App() {
// input要素を指し示すための「マジックハンド(ref)」を作ります
const inputRef = useRef(null);

const handleFocusClick = () => {
// マジックハンドがうまくinputを指していれば、フォーカスを当てます!
if (inputRef.current) {
inputRef.current.focus();
inputRef.current.style.borderColor = ‘#007bff’; // ついでに枠線の色も変えちゃおう
}
};

return (

);
}

どうでしょう?
親(`App`)で作った `inputRef` が、`CustomInput` という壁をすり抜けて、中の `` タグまでしっかり届いているのが分かりますよね。

—

3. ここでつまずきやすい!TypeScriptの型付けの罠

初心者の頃、筆者もここで何度も頭を抱えたのですが、`forwardRef` をTypeScriptで書くとき、型エラーに悩まされがちです。

ポイントは以下の2つだけ!呪文のように覚えてしまいましょう。

forwardRef((props, ref) => { … })

1. 第1ジェネリクス(DOMの型):
「最終的にどのHTML要素を指したいのか」を指定します。

  • `input` なら `HTMLInputElement`
  • `button` なら `HTMLButtonElement`
  • `div` なら `HTMLDivElement`

です。迷ったらエディタの補完を信じましょう!

2. 第2ジェネリクス(Propsの型):
普段コンポーネントを作るときと同じように、自分が定義したPropsの型(InterfaceやType Alias)を渡します。Propsが何もない場合でも、空のオブジェクト型 `{}` を指定してあげるとTypeScriptが機嫌よく動いてくれます。

—

4. チーフアーキテクトからの実務アドバイス

最後に、現場で設計をする上での大切な心構えを一つ。

「DOMを直接操作する(`ref` を使う)」というのは、実はReactの基本理念である「データ駆動型(状態が変われば画面も勝手に変わる)」という世界観から少し外れる、いわば「裏技・特例措置」に近いものです。

なんでもかんでも `forwardRef` や `ref` でDOMを操作しようとすると、コードがスパゲッティのように複雑になってしまい、後から自分で自分の首を絞めることになります。

原則として:

  • データの変更や表示の切り替えは、基本的に `useState` や Props などの「状態」で行う。
  • どうしても「フォーカスを当てる」「スクロール位置を制御する」「アニメーションやメディア(動画など)を再生する」といった、ブラウザのDOMそのものを動かす必要がある瞬間だけ `forwardRef` を使う。

このメリハリを持つだけで、あなたの書くReactコードは一気にプロのアーキテクトのそれに近づきます。

最初は難しく感じるかもしれませんが、何度か書いていくうちに「あ、ここはパスが必要なやつだな」と直感で分かるようになりますよ。焦らず、ご自身のペースで一歩ずつ進めていきましょう!応援しています!

コメント

タイトルとURLをコピーしました