Next.jsによるWebアプリケーション開発概論

Propsによるデータの受け渡し

4Next.js基礎:ReactコンポーネントとJSX・Propsの基本
Next.jsTailwind CSSアプリ開発開発Web開発

この節で学ぶこと

この節では、React における Props(プロップス) が何なのか、なぜ必要なのか、どう渡してどう受け取るのかを学びます。

React 公式では、props はコンポーネント同士がやり取りするための情報であり、親コンポーネントが子コンポーネントへ props を渡す ことで UI を調整できると説明されています。

さらに、props には文字列だけでなく、オブジェクト、配列、関数、JSX も渡せます。

この節の到達目標は4つです。

  1. props を「部品に渡す設定値」ではなく、親から子へ渡すデータ として説明できることです。
  2. 2つ目は、JSX タグ側で props を渡し、子コンポーネント側で props を受け取れることです。
  3. 分割代入、デフォルト値、children の基本を理解することです。
  4. props があることで、同じコンポーネントを中身だけ変えて再利用できると実感することです。

Props とは何か

親コンポーネントから子コンポーネントへ渡す情報

React 公式では、props はコンポーネント同士がコミュニケーションするための仕組みで、すべての親コンポーネントは子コンポーネントへ props を渡せる と説明されています。

HTML の属性に少し似ていますが、独自コンポーネントにはもっと自由にデータを渡せます。

たとえば、同じ「プロフィール画像」コンポーネントでも、表示する人物やサイズが毎回同じとは限りません。

もし props がなければ、コンポーネントの中身を書き換えないと別の人物を表示できません。

props があると、部品の形はそのままに、中身だけを外から変えられる ようになります。これはコンポーネントベース開発の中心にある考え方です。

関数の引数に近い考え方

React 公式は、props は関数における引数と同じ役割を持つと説明しています。実際、React コンポーネント関数は 1つの引数として props オブジェクトを受け取る という見方ができます。

この見方を持てると、props は急に分かりやすくなります。

JavaScript の普通の関数でも、引数を変えれば結果が変わります。React コンポーネントも同じで、渡す props を変えると表示が変わる、と考えると自然です。

まずは HTML の属性から考える

組み込みタグにも props がある

React 公式では、classNamesrcaltwidthheight などは、<img> のような組み込みタグへ渡せる props だと説明しています。ReactDOM は HTML 標準に沿ってそれらを扱います。

export default function Profile() {
  return (
    <img
      className="avatar"
      src="/avatar.png"
      alt="プロフィール画像"
      width={100}
      height={100}
    />
  )
}

このコードでも、すでに props を使っています。

srcaltwidth も、見た目や内容を決めるために JSX タグへ渡している情報です。つまり、props は「自作コンポーネントを学ぶ前に、実はすでに使っている概念」でもあります。

自作コンポーネントにも同じ考え方を使う

React 公式では、組み込みタグの props はあらかじめ決まっている一方で、自分で作ったコンポーネントには自由な props を渡せる と説明しています。

function Avatar() {
  return <p>アバターです</p>
}

export default function Page() {
  return <Avatar />
}

この時点では Avatar に何も渡していません。

でも、ここへ「誰の画像か」「何pxで表示するか」のような情報を渡せるようになると、コンポーネントは一気に使いやすくなります。そこで登場するのが props です。

Props を渡す

JSX タグ側で属性のように書く

React 公式の “Passing props to a component” では、まず親側で <Avatar person={...} size={100} /> のように props を渡す流れが示されています。

function Avatar() {
  return <p>アバターです</p>
}

export default function Profile() {
  return (
    <Avatar
      person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
      size={100}
    />
  )
}

ここで大事なのは、見た目が HTML 属性に似ていても、渡している内容はもっと自由だという点です。React 公式も、props には オブジェクト、配列、関数を含む任意の JavaScript 値 を渡せると説明しています。

文字列だけでなく、数値やオブジェクトも渡せる

React 公式の例では、size={100} のように数値を渡し、person={{ ... }} のようにオブジェクトも渡しています。これはとても重要です。props は単なる文字列の受け渡しではありません。

export default function ProductPage() {
  return (
    <ProductCard
      title="本革バッグ"
      price={19800}
      product={{ id: 1, stock: 5 }}
    />
  )
}

このように props を使うと、UI コンポーネントが「固定表示の部品」から「データに応じて変わる部品」へ変わります。React の強みは、まさにこの データ駆動の UI を部品単位で書けることにあります。

Props を受け取る

props オブジェクトとして受け取る

React 公式では、コンポーネント関数は props という引数を1つ受け取り、その中から props.personprops.size のように値を読む形をまず示しています。

function Avatar(props) {
  const person = props.person
  const size = props.size

  return (
    <img
      src={`/images/${person.imageId}.jpg`}
      alt={person.name}
      width={size}
      height={size}
    />
  )
}

これが基本形です。

「親から渡された情報が、props という箱に入ってくる」と考えると理解しやすいです。最初の一歩としては、この形で読むのが安全です。

分割代入で受け取る

React 公式では、通常は props 全体を使うより、分割代入 で function Avatar({ person, size }) のように受け取ることが多いと説明しています。これは JavaScript の destructuring 構文です。

function Avatar({ person, size }) {
  return (
    <img
      src={`/images/${person.imageId}.jpg`}
      alt={person.name}
      width={size}
      height={size}
    />
  )
}

この書き方は、慣れるとかなり読みやすいです。

「このコンポーネントは personsize を受け取る」と関数の入口で一目で分かるからです。React 公式も、通常は props 全体より分割代入の方がよく使われると説明しています。

Props を使うと再利用できる

同じコンポーネントを違う内容で使える

React 公式では、1つの Avatar コンポーネントに別々の personsize を渡して、複数パターンの表示を作る例が示されています。親側は値を変えるだけで、子側の使い方を意識しすぎずに済みます。

function Avatar({ person, size }) {
  return (
    <img
      src={`/images/${person.imageId}.jpg`}
      alt={person.name}
      width={size}
      height={size}
    />
  )
}

export default function ProfileList() {
  return (
    <div>
      <Avatar
        person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }}
        size={100}
      />
      <Avatar
        person={{ name: 'Aklilu Lemma', imageId: 'OKS67lh' }}
        size={80}
      />
      <Avatar
        person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
        size={50}
      />
    </div>
  )
}

このコードの価値は大きいです。

Avatar を3回書いているように見えて、実際には 1つの部品を3通りのデータで使い回している だけです。React 公式も、props によって親と子を独立して考えやすくなると説明しています。

親と子を別々に考えやすくなる

React 公式は、props によって親コンポーネント側では「何を渡すか」、子コンポーネント側では「受け取ったものをどう表示するか」を分けて考えやすくなると説明しています。

これは設計上かなり大事です。

親はデータの用意に集中し、子は UI の見せ方に集中できます。この分離があるから、コンポーネントベース開発は保守しやすくなります。 props は、単なる文法ではなく 責務分離のための仕組み でもあります。

デフォルト値

props が渡されなかったときの初期値

React 公式では、分割代入の中で size = 100 のように書くことで、props のデフォルト値を設定できると説明しています。これは その props が未指定、または undefined のときだけ 使われます。 null0 では適用されません。

function Avatar({ person, size = 100 }) {
  return (
    <img
      src={`/images/${person.imageId}.jpg`}
      alt={person.name}
      width={size}
      height={size}
    />
  )
}

この書き方を知っておくと、コンポーネントの使い勝手が上がります。

「たいていは 100px で表示したいが、必要なら外から変えたい」という設計がしやすくなるからです。React 公式でも、未指定のときにだけデフォルト値が使われることが明記されています。

children という特別な props

タグの中に書いた内容は children になる

React 公式では、独自コンポーネントのタグの中に何かを書いてネストすると、その内容は親コンポーネントに children props として渡されると説明しています。

function Card({ children }) {
  return <div className="card">{children}</div>
}

export default function Page() {
  return (
    <Card>
      <p>この文章は children として渡されています。</p>
    </Card>
  )
}

これはとても便利です。

親コンポーネントは「枠だけ」を定義し、中に入る具体的な内容は使う側に任せられます。React 公式も、children は “hole” のように考えられ、親がそこへ任意の JSX を差し込めると説明しています。

ラッパー系コンポーネントで特に強い

React 公式では、children は panels や grids などの 視覚的なラッパー によく使うと説明しています。

たとえば、共通カード、モーダル、セクション枠、レイアウト枠などは children と非常に相性がよいです。

これは今後 Next.js の layout.tsx や UI コンポーネント設計でもとてもよく出てきます。つまり children は、小技ではなく、React の組み立て方そのものに関わる props です。

スプレッド構文による props 転送

...props でまとめて渡せる

React 公式では、props の受け渡しが繰り返しになりすぎる場合、JSX spread syntax を使ってまとめて子へ転送できると説明しています。たとえば Profile が受け取った props を、そのまま Avatar に渡すような場面です。

function Profile(props) {
  return (
    <div className="card">
      <Avatar {...props} />
    </div>
  )
}

これは便利ですが、React 公式は 使いすぎに注意 とも説明しています。 every other component で多用するなら設計を見直した方がよい可能性があります。

最初は多用しなくてよい

初心者の段階では、props はまず明示的に書く方が理解しやすいです。

person={person}size={size} と書いた方が、どんな情報が渡っているのか一目で分かるからです。スプレッド構文は便利ですが、props の流れが見えにくくなることもあります。React 公式も「短くはなるが、節度を持って使う」ことを勧めています。

Props と画面表示の関係

props が変わると UI が変わる

React 公式では、props に応じてコンポーネントの描画結果が変わる例を通して、props は UI を調整するノブのようなものだと説明しています。

たとえば次のようなコンポーネントは、渡す name が変われば表示も変わります。

function Greeting({ name }) {
  return <p>こんにちは、{name}さん</p>
}

export default function Page() {
  return (
    <>
      <Greeting name="佐藤さん" />
      <Greeting name="山田さん" />
    </>
  )
}

この時点で、props は単なるデータではなく、画面表示を決める入力値 だと分かります。

つまり、React コンポーネントは props を受け取って JSX を返す関数、と言い換えられます。これは前節の「関数としてのコンポーネント」の理解ともつながります。

初心者がつまずきやすい点

props は親から子へ流れる

React の props は、基本的に 親から子へ 流れます。

この向きが崩れると、一気に分かりにくくなります。React 公式の props 解説も、親が子へ情報を渡すという構図で一貫しています。

つまり、子コンポーネントの中で「親の props を直接変える」ような考え方はしません。

まずは「親が渡す」「子が受け取る」「子はそれを使って表示する」という片方向の流れをしっかり押さえるのが大切です。

props.person.name と分割代入を混同する

最初は、次の2つの書き方が同じ意味だと分かりにくいことがあります。React 公式では、分割代入は props.person を取り出す短い書き方だと説明しています。

function Avatar(props) {
  return <p>{props.person.name}</p>
}
function Avatar({ person }) {
  return <p>{person.name}</p>
}

どちらも正しいです。

最初は props オブジェクトの形で読んで、慣れてきたら分割代入へ移る、という順番でも十分です。

default value は null では効かない

React 公式では、デフォルト値は props が missing または undefined のときだけ 使われ、null0 を渡したときは使われないと明記されています。

これは地味ですが大切です。

「何も渡していない」のか、「わざと null を渡している」のかは意味が違うからです。ここを区別できると、props の挙動がかなり素直に理解できるようになります。

練習問題

問1

React における props の説明として最も適切なものはどれですか。

A. コンポーネント同士でデータをやり取りするための仕組み

B. CSS だけを設定するファイル

C. データベース接続専用の変数

D. JSX を禁止するルール

答え

A

解説

React 公式では、props はコンポーネント同士がコミュニケーションするための仕組みで、親コンポーネントが子へ情報を渡せると説明しています。

問2

次のうち、props として渡せるものとして正しい説明はどれですか。

A. 文字列しか渡せない

B. 数値しか渡せない

C. JavaScript のさまざまな値を渡せる

D. 関数は絶対に渡せない

答え

C

解説

React 公式では、props には文字列だけでなく、オブジェクト、配列、関数など、任意の JavaScript 値を渡せると説明しています。

問3

props を分割代入で受け取る書き方として正しいものはどれですか。

A. function Avatar(props.person, props.size) {} B. function Avatar({ person, size }) {} C. function Avatar[person, size] {} D. function Avatar(person: size) {}

答え

B

解説

React 公式では、function Avatar({ person, size }) の形で props を分割代入できると説明しています。これは props.personprops.size を取り出すのと同じ意味です。

問4

children props について正しいものはどれですか。

A. 画像 URL 専用の props

B. JSX タグの中にネストした内容が渡される特別な props

C. 必ず文字列だけが入る props

D. next/image 専用の props

答え

B

解説

React 公式では、独自コンポーネントタグの中にネストした内容は children props として親コンポーネントへ渡されると説明しています。

問5

props のデフォルト値について正しいものはどれですか。

A. size = 100 のように分割代入で設定できる

B. null を渡しても必ずデフォルト値が使われる

C. 0 を渡しても必ずデフォルト値が使われる

D. React では props にデフォルト値は設定できない

答え

A

解説

React 公式では、function Avatar({ person, size = 100 }) のように分割代入でデフォルト値を設定できると説明しています。これは未指定または undefined の場合にのみ使われ、null0 では使われません。

まとめ

props は、React コンポーネントを 固定の部品 ではなく データに応じて変わる部品 にするための仕組みです。React 公式では、親コンポーネントが子コンポーネントへ情報を渡すために props を使い、文字列だけでなくオブジェクト、配列、関数、JSX まで渡せると説明しています。 props は関数における引数のような役割を持ち、コンポーネントの表示内容を外から調整できます。

この節で特に押さえたいのは、次の5点です。

  • props は親から子へ渡すデータである。
  • コンポーネントは props オブジェクト、または分割代入で受け取れる。
  • デフォルト値は未指定や undefined のときだけ使われる。
  • children はネストした JSX を受け取る特別な props である。
  • props があるから、同じ部品を何通りにも再利用できる。

ここが理解できると、React コンポーネントは急に実用的に見えてきます。

「ただの関数」だったものが、「外からデータを受け取り、見た目を変えられる部品」へ変わるからです。次の節で TypeScript による Props 型定義を学ぶと、この props の流れにさらに安全性が加わります。

参考文献

  • React Docs, Passing Props to a Component
  • React Docs, Describing the UI
  • React Docs, Conditional Rendering
教材トップへ戻る