Next.jsで学ぶReact講座 | Reactの基本操作 – 名前だけを変えて挨拶するコンポーネント

Next.js
スポンサーリンク

このテーマのゴール

ここでやりたいのは、「カード」という“部品”を1つ作って、タイトルと本文だけ差し替えて何度も使えるようにすることです。

前の「名前だけ変えて挨拶」と同じ発想ですが、
もう少し“実際のアプリっぽい UI”に近づけた形で、props の使い方とコンポーネントの再利用を体で覚えていきます。


完成イメージを先に見てみる

「カード」コンポーネントの例

まずはゴールのコードを見てみましょう。

// components/Card.tsx
type CardProps = {
  title: string;
  body: string;
};

export function Card({ title, body }: CardProps) {
  return (
    <div
      style={{
        border: "1px solid #e5e7eb",
        borderRadius: "8px",
        padding: "12px 16px",
        backgroundColor: "white",
        boxShadow: "0 1px 3px rgba(15, 23, 42, 0.08)",
        marginBottom: "12px",
      }}
    >
      <h2 style={{ fontSize: "18px", marginBottom: "4px" }}>{title}</h2>
      <p style={{ fontSize: "14px", color: "#4b5563" }}>{body}</p>
    </div>
  );
}
TSX
// app/page.tsx
import { Card } from "./components/Card";

export default function Page() {
  return (
    <main
      style={{
        padding: "24px",
        fontFamily: "system-ui, sans-serif",
        backgroundColor: "#f3f4f6",
        minHeight: "100vh",
      }}
    >
      <h1 style={{ fontSize: "24px", marginBottom: "16px" }}>カードコンポーネントの例</h1>

      <Card
        title="お知らせ"
        body="明日の勉強会は19時から開始します。Zoomリンクはメールをご確認ください。"
      />

      <Card
        title="新機能のご案内"
        body="ダークモードが利用できるようになりました。設定画面から切り替えできます。"
      />

      <Card
        title="メンテナンス情報"
        body="今週末の深夜にサーバーメンテナンスを予定しています。サービスが一時的にご利用いただけません。"
      />
    </main>
  );
}
TSX

画面には、枠で囲まれたカードが3つ並び、
それぞれ「タイトル」と「本文」だけが違う状態になります。


props で「タイトル」と「本文」を受け取る仕組み

CardProps という“約束”を作る

まず、Card コンポーネントの定義部分を分解してみます。

type CardProps = {
  title: string;
  body: string;
};
TSX

ここでやっているのは、

「このカードは titlebody という2つの文字列を受け取ります」

という“約束”を TypeScript で書いている、ということです。

これがあることで、

  • title を渡し忘れたらエラーになる
  • body に数字を渡そうとしたらエラーになる

つまり、「間違った使い方」をコンパイル時に止めてくれます。

コンポーネントの引数で props を受け取る

次に、この部分。

export function Card({ title, body }: CardProps) {
  return (
    ...
  );
}
TSX

ここは、

  • CardCardProps 型のオブジェクトを受け取る
  • そのオブジェクトから titlebody を取り出して使う

という意味です。

イメージとしては、こう呼ばれている感じです。

Card({ title: "お知らせ", body: "明日の勉強会は…" });
Card({ title: "新機能のご案内", body: "ダークモードが…" });
TSX

JSX では <Card title="お知らせ" body="…" /> と書きますが、
中身では「{ title: ..., body: ... } というオブジェクト」が渡されている、と考えると分かりやすいです。


同じカードを「中身だけ変えて」何度も使う

親コンポーネントから値を渡す

page.tsx 側の使い方をもう一度見てみます。

<Card
  title="お知らせ"
  body="明日の勉強会は19時から開始します。Zoomリンクはメールをご確認ください。"
/>

<Card
  title="新機能のご案内"
  body="ダークモードが利用できるようになりました。設定画面から切り替えできます。"
/>
TSX

やっていることはとてもシンプルで、

  • 1つ目のカードには「お知らせ」「明日の勉強会は…」という文字列を渡す
  • 2つ目のカードには「新機能のご案内」「ダークモードが…」という文字列を渡す

というだけです。

コンポーネントの中身(枠線・余白・タイトルの位置など)は完全に同じ。
違うのは props として渡している titlebody の値だけ

これが「タイトルと本文を props で受け取るカードコンポーネント」の本質です。


配列+map で「カード一覧」にする

データを配列にまとめてから描画する

実際のアプリでは、「お知らせ」や「記事」などのデータを配列で持っておいて、
それを map でカードに変換することが多いです。

type Info = {
  id: number;
  title: string;
  body: string;
};

const infos: Info[] = [
  {
    id: 1,
    title: "お知らせ",
    body: "明日の勉強会は19時から開始します。Zoomリンクはメールをご確認ください。",
  },
  {
    id: 2,
    title: "新機能のご案内",
    body: "ダークモードが利用できるようになりました。設定画面から切り替えできます。",
  },
  {
    id: 3,
    title: "メンテナンス情報",
    body: "今週末の深夜にサーバーメンテナンスを予定しています。",
  },
];

export default function Page() {
  return (
    <main style={{ padding: "24px" }}>
      <h1>お知らせ一覧</h1>
      {infos.map((info) => (
        <Card key={info.id} title={info.title} body={info.body} />
      ))}
    </main>
  );
}
TSX

ここでの大事なポイントは、

  • 「データ(infos)」と「見た目(Card)」を分けて考えている
  • データが増えても、配列に追加するだけでカードが増える

というところです。

カードコンポーネントは「見た目のテンプレート」、
配列は「中身のデータの集まり」──この役割分担ができると、一気にアプリっぽくなります。


まとめ:このカードコンポーネントからつかんでほしいこと

このテーマで本当に持ち帰ってほしいのは、次の感覚です。

コンポーネントは「枠(テンプレート)」で、props は「その枠に流し込む中身」
タイトルや本文のような“変わる部分”は props にして、見た目の構造はコンポーネントに閉じ込める
データを配列で持っておいて、map でカードに変換すると「一覧表示」が自然に書ける

ここが腑に落ちると、

  • 記事カード
  • 商品カード
  • プロフィールカード

みたいな UI を、全部「同じ Card コンポーネント+違う props」で表現できるようになります。

もしよければ、この Card に「小さなフッターテキスト(例:投稿日)」を追加してみてください。
footer みたいな props を増やしてみると、「props を増やしてコンポーネントの表現力を上げる」感覚がさらにつかめます。

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