【入門編】 ジェネリックコンポーネントによるPropsの型付け – React実践ガイド

こんにちは!Reactの世界へようこそ。
フロントエンドの最前線でコードを書いていると、「あぁ、もっとスマートに書きたいな」と壁にぶつかる瞬間がありますよね。

今日は、そんな皆さんの開発ライフを劇的に楽にする、「ジェネリックコンポーネント」という少し魔法のようなテクニックについてお話しします。「ジェネリック? なんか難しそう…」と身構える必要は全くありません。大丈夫、一緒に紐解いていきましょう。

—

「何でも入る箱」と「中身が決まった箱」の話

例えば、あなたがカフェの店員さんだと想像してください。

お客様から注文を受けるとき、「何が入っているか分からない箱」を渡されるよりも、「この箱にはサンドイッチが入っています」「この箱にはコーヒーが入っています」と、中身に合わせて箱のラベルが自動で変わる方が、ミスがなくて安心ですよね?

Reactのコンポーネントも同じです。
今までは、「どんなデータが来てもいいように、とりあえず大雑把な型をつけておくか…」と妥協していた部分がありませんか? これを解決するのが、ジェネリック(Generic)という技術です。

ジェネリックとは、「使うときに中身の型を教えてあげることで、そのコンポーネント専用の型に早変わりさせる」という仕組みのことなんです。

—

実際にコードで見てみよう:リスト表示の例

例えば、「名前のリスト」を表示するコンポーネントを作ったとします。でも、後から「年齢のリスト」や「商品情報のリスト」も表示したくなった時、わざわざ似たようなコンポーネントを何度も作るのは面倒ですよね。

そこで、ジェネリックの出番です。`` という記号を使って、「ここには後で型が入るよ!」と宣言してあげます。

// Tというのは「Type(型)」の頭文字です。
// 「T」という名前は慣習ですが、なんでもOKです。
interface ListProps {
items: T[]; // T型のデータの配列だよ
renderItem: (item: T) => React.ReactNode; // T型のデータをどう表示するか決めるよ
}

// コンポーネント定義。 をつけることでジェネリック対応になります
export const GenericList = ({ items, renderItem }: ListProps) => {
return (

    {items.map((item, index) => (

  • {renderItem(item)}
  • ))}

);
};

どう使うの?

使う側で、「今回はユーザー名を表示するよ!」と教えてあげるだけです。

// 使う場所
const users = [{ id: 1, name: ‘田中さん’ }, { id: 2, name: ‘佐藤さん’ }];

{item.name}}
/>

これの何が嬉しいかというと、`renderItem` の中で `item.` と打った瞬間に、エディタが「あ、このデータには `name` があるよね?」とサジェストしてくれるんです。「型を自分で書かなくても、勝手に中身を察してくれる」。これが開発現場でどれほど心強いか、伝わるでしょうか。

—

初学者がつまずきやすいポイントへのフォロー

ジェネリックを学ぶとき、多くの人が「`` とか `` とか、記号が多すぎてパニック!」となります。

でも、最初は「Tはただのプレースホルダー(仮置き)」と考えてください。
「もし中身が文字列なら `T` は `string` になる」
「もし中身がユーザー情報なら `T` は `User` 型になる」
それだけのことです。

もしコードが赤く波打ってエラーが出ても、それは「あなたが悪い」のではなく、「TypeScriptという親切な相棒が、あなたのミスを事前に防いでくれている」というサインです。エラーメッセージを怖がらずに、「教えてくれてありがとう!」と返してあげてくださいね。

—

最後に:なぜこのテクニックが最強なのか

現場で長く生き残るコードの秘訣は、「変更に強いこと」です。
ジェネリックコンポーネントを使うと、コンポーネントを「使い捨て」にするのではなく、「柔軟な部品」として資産化できます。

最初は難しく感じるかもしれませんが、一度この「型を動的に決める」感覚を掴むと、もう以前の書き方には戻れないはずです。

皆さんが書くコードが、もっと自由で、もっと安全で、そして何より「楽しく」なることを応援しています。分からないことがあれば、いつでも何度でも立ち止まって、またここに戻ってきてくださいね。

それでは、素晴らしいReactライフを!

コメント

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