【React】Propsでコンポーネントに値を渡す方法

JavaScript

こんにちは、かつコーチです。

前回は仮想DOMの仕組みを見ながら、Reactがなぜ速いのかを解説しました。

今回は、React学習で最初につまずきやすいポイントの一つ「Props」を扱います。

コンポーネントに値を渡すための仕組みなのですが、最初は「なぜ必要なのか」がピンとこない人が多いです。

具体例を交えながら、順番に理解していきましょう。

Propsとは?

親コンポーネントから子コンポーネントに渡す「引数」

Propsとは、親コンポーネントから子コンポーネントに値を渡すための仕組みです。

「プロパティ(Property)」の略で、コンポーネントを関数だと考えると、Propsは「その関数に渡す引数」に近いイメージです。

function Greeting(props: { name: string }) {
  return <p>こんにちは、{props.name}さん!</p>;
}

function App() {
  return <Greeting name="かつコーチ" />;
}

App から Greetingname="かつコーチ" という値を渡し、Greeting 側は props.name として受け取っています。

なぜPropsが必要なのか

Reactの大きな強みは、UIを部品(コンポーネント)に分割して再利用できることです。

ただし、部品を使い回すには「同じ見た目のコンポーネントに、違うデータを表示させたい」という場面が必ず出てきます。

たとえばユーザー一覧画面で、名前だけが違うカードを何枚も表示したいケースです。

このとき、コンポーネントの中身を毎回書き換えるのではなく、外から値を注入できれば効率的です。

Propsはまさにこの「外から値を注入する」ための仕組みで、Reactコンポーネントを部品として再利用可能にする土台になっています。

基本の書き方

親から子へ値を渡す

Propsを渡す側は、JSXの属性のようにして値を渡します。

function UserCard(props: { name: string; age: number }) {
  return (
    <div>
      <p>名前:{props.name}</p>
      <p>年齢:{props.age}歳</p>
    </div>
  );
}

function App() {
  return <UserCard name="佐藤太郎" age={28} />;
}

文字列は name="佐藤太郎" のようにダブルクォートで、数値や変数を渡すときは age={28} のように波括弧で囲みます。

複数のPropsをまとめて渡す

Propsが増えてくると、1つずつ書くのが面倒になってきます。

そんなときは、オブジェクトをスプレッド構文で展開して渡すこともできます。

const userData = { name: "佐藤太郎", age: 28 };

function App() {
  return <UserCard {...userData} />;
}

{...userData} と書くことで、オブジェクトのキーがそのままPropsの名前として渡されます。

TypeScriptで型を付ける

Propsの型は、多くの場合 interfacetype で定義してから使います。

interface UserCardProps {
  name: string;
  age: number;
}

function UserCard({ name, age }: UserCardProps) {
  return (
    <div>
      <p>名前:{name}</p>
      <p>年齢:{age}歳</p>
    </div>
  );
}

props.name と毎回書く代わりに、分割代入で { name, age } と受け取る書き方もよく使われます。

型を明示しておくと、渡し忘れや型違いをエディタが教えてくれるので、実務ではほぼ必須の習慣です。

よくあるつまずきポイント

Propsを直接書き換えてしまう

私が初めてPropsを扱ったとき、受け取った値をコンポーネントの中で直接書き換えようとして、動作がおかしくなったことがあります。

❌ Before:Propsを直接書き換える

interface UserCardProps {
  name: string;
}

function UserCard(props: UserCardProps) {
  // propsは読み取り専用。直接書き換えるのはNG
  props.name = props.name + "さん";
  return <p>{props.name}</p>;
}

このコードは一見動いているように見えても、TypeScriptの型エラーになりますし、React全体の設計思想にも反しています。

Propsは親から渡された読み取り専用のデータであり、子コンポーネント側で書き換えることは想定されていません。

✅ After:新しい変数に加工してから使う

interface UserCardProps {
  name: string;
}

function UserCard(props: UserCardProps) {
  const displayName = `${props.name}さん`;
  return <p>{displayName}</p>;
}

受け取った値を書き換えるのではなく、別の変数に加工結果を入れて使うようにすれば、Propsの不変性を保ったまま目的を達成できます。

「Propsは書き換えない」というルールを意識するだけで、この手のバグはかなり減らせます。

応用:一歩先の使い方

children Propsでタグの中身を渡す

children という特別なPropsを使うと、コンポーネントのタグに囲まれた中身をそのまま渡せます。

function Card({ children }: { children: React.ReactNode }) {
  return <div className="card">{children}</div>;
}

function App() {
  return (
    <Card>
      <p>ここがchildrenとして渡される内容です</p>
    </Card>
  );
}

レイアウト用のコンポーネントを作るときによく使われる書き方で、中身を柔軟に差し替えられるのが特徴です。

Propsにデフォルト値を与える

値が渡されなかった場合に備えて、デフォルト値を設定しておくこともできます。

interface ButtonProps {
  label?: string;
}

function SubmitButton({ label = "送信" }: ButtonProps) {
  return <button>{label}</button>;
}

label?: string? を付けて任意項目にし、分割代入時に label = "送信" とデフォルト値を書いておくと、Props未指定でも安全に動作します。

まとめ

この記事のポイント

  • Propsは親コンポーネントから子コンポーネントへ値を渡す仕組みで、関数の引数に近いイメージ
  • コンポーネントを再利用可能な部品にするために欠かせない仕組み
  • Propsは読み取り専用なので、直接書き換えず新しい変数に加工して使う
  • children を使うとタグに囲まれた中身をそのまま渡せる
  • デフォルト値を設定すれば、Props未指定でも安全に動作する

次に読むべき記事

Propsは「外から渡される値」でしたが、コンポーネント自身が持つ値を扱いたい場面も出てきます。

次回は、そのための仕組みである「useState」の基本を解説します。

→ 次の記事:useStateの基本:状態を持つコンポーネントを作る

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