コンポーネントにpropsを渡す
Reactコンポーネントは、propsを使って互いに通信します。すべての親コンポーネントは、propsを渡すことで子コンポーネントに情報を伝えることができます。propsはHTML属性を思い起こさせるかもしれませんが、オブジェクト、配列、関数を含むあらゆるJavaScriptの値を渡すことができます。
学習内容
- コンポーネントにpropsを渡す方法
- コンポーネントからpropsを読み取る方法
- propsのデフォルト値を指定する方法
- コンポーネントにJSXを渡す方法
- propsが時間とともにどのように変化するか
馴染みのあるprops
propsとは、JSXタグに渡す情報のことです。例えば、className、src、alt、width、heightは、<img>に渡すことができるpropsの一部です:
<img>タグに渡せるpropsは事前に定義されています(ReactDOMはHTML標準に準拠しています)。しかし、独自のコンポーネント、例えば<Avatar>には、カスタマイズするために任意のpropsを渡すことができます。その方法は以下の通りです!
コンポーネントにpropsを渡す
このコードでは、Profileコンポーネントは、その子コンポーネントであるAvatarに何もpropsを渡していません:
Avatarにpropsを渡すには、2つのステップがあります。
ステップ1: 子コンポーネントにpropsを渡す
まず、Avatarにいくつかのpropsを渡します。例えば、2つのpropsを渡してみましょう:person(オブジェクト)とsize(数値):
補足
person=の後の二重波括弧が混乱する場合は、それらは単にJSXの波括弧内のオブジェクトであることを思い出してください。
これで、Avatarコンポーネント内でこれらのpropsを読み取ることができます。
ステップ2: 子コンポーネント内でpropsを読み取る
これらのpropsは、その名前person, sizeをカンマで区切って({と})の間に直接記述することで読み取ることができます。これはfunction Avatarの直後に記述します。これにより、変数のようにAvatarコード内でそれらを使用できるようになります。
Avatarに、レンダリングのためにpersonとsizepropsを使用するロジックを追加すれば完了です。
これで、異なるpropsを使ってAvatarをさまざまな方法でレンダリングするように設定できます。値を調整してみてください!
propsを使用すると、親コンポーネントと子コンポーネントを独立して考えることができます。例えば、personやsizeのpropsをProfile内で変更する際に、Avatarがそれらをどのように使用するかを考える必要はありません。同様に、Avatarがこれらのpropsをどのように使用するかを変更する際も、Profileを見る必要はありません。
propsは、調整可能な「つまみ」のようなものと考えることができます。関数の引数と同じ役割を果たします。実際、propsはコンポーネントの唯一の引数です!Reactコンポーネント関数は、単一の引数であるpropsオブジェクトを受け取ります:
通常、propsオブジェクト全体は必要ないため、個々のpropsに分割代入します。
落とし穴
propsのデフォルト値を指定する
値が指定されていない場合にフォールバックするデフォルト値をpropsに与えたい場合は、パラメータの直後に=とデフォルト値を置くことで、分割代入で行うことができます:
これで、<Avatar person={...} />がsizepropsなしでレンダリングされると、sizeは100に設定されます。
デフォルト値は、sizepropsが欠落している場合、またはsize={undefined}を渡した場合にのみ使用されます。しかし、size={null}またはsize={0}を渡すと、デフォルト値は使用されません。
JSXスプレッド構文を使用したpropsの転送
時には、propsの受け渡しが非常に繰り返しになることがあります:
繰り返しのコードに問題はありません。むしろ読みやすくなることもあります。しかし、簡潔さを重視する場合もあるでしょう。このProfileがAvatarに対して行うように、一部のコンポーネントはすべてのpropsを子コンポーネントに転送します。propsを直接使用しないため、より簡潔な「スプレッド」構文を使用することが理にかなっています:
これにより、Profileのすべてのpropsが、それぞれの名前を列挙することなくAvatarに転送されます。
スプレッド構文は控えめに使用してください。他のコンポーネントで頻繁に使用している場合、何か問題がある可能性があります。多くの場合、コンポーネントを分割し、子要素としてJSXを渡すべきであることを示しています。次にそれについて詳しく説明します!
子要素としてJSXを渡す
組み込みのブラウザタグをネストすることは一般的です:
独自のコンポーネントも同じようにネストしたい場合があります:
JSXタグ内にコンテンツをネストすると、親コンポーネントはそのコンテンツをchildrenという名前のpropsとして受け取ります。例えば、以下のCardコンポーネントは、childrenpropsに<Avatar />が設定されて受け取られ、それをラッパーdiv内でレンダリングします:
以下の<Avatar>を<Card>内でテキストに置き換えてみて、Cardコンポーネントがどのようにネストされたコンテンツをラップできるかを確認してください。内部で何がレンダリングされているかを「知る」必要はありません。この柔軟なパターンは多くの場所で見られます。
コンポーネントのchildrenpropsは、親コンポーネントが任意のJSXで「埋める」ことができる「穴」があると考えることができます。childrenpropsは、パネルやグリッドなどの視覚的なラッパーによく使用されます。

イラスト:Rachel Lee Nabors
propsが時間とともに変化する仕組み
以下のClockコンポーネントは、親コンポーネントから2つのpropsを受け取ります:colorとtimeです。(親コンポーネントのコードは、まだ詳しく説明しないstateを使用しているため省略されています。)
以下のセレクトボックスで色を変更してみてください:
この例は、コンポーネントが時間とともに異なるpropsを受け取る可能性があることを示しています。propsは常に静的ではありません!ここでは、timepropsは毎秒変化し、colorpropsは別の色を選択すると変化します。propsは、コンポーネントのデータを開始時だけでなく、任意の時点で反映します。
しかし、propsはイミュータブル(コンピュータサイエンスの用語で「変更不可」を意味します)です。コンポーネントがpropsを変更する必要がある場合(例えば、ユーザーの操作や新しいデータに応じて)、親コンポーネントに異なるprops—新しいオブジェクト!—を渡すように「依頼」しなければなりません。古いpropsはその後捨てられ、最終的にJavaScriptエンジンがそれらが占めていたメモリを回収します。
「propsを変更しよう」としないでください。ユーザー入力に応答する必要がある場合(選択した色を変更するなど)、「stateを設定する」必要があります。これはState: コンポーネントのメモリで学ぶことができます。
まとめ
- propsを渡すには、HTML属性と同じようにJSXに追加します。
- propsを読み取るには、
function Avatar({ person, size })のような分割代入構文を使用します。 - デフォルト値は
size = 100のように指定でき、これはpropsが欠落している場合やundefinedの場合に使用されます。 - すべてのpropsは
<Avatar {...props} />のようなJSXスプレッド構文で転送できますが、使いすぎには注意しましょう! - ネストされたJSX(例:
<Card><Avatar /></Card>)は、Cardコンポーネントのchildrenpropとして表示されます。 - propsは読み取り専用のスナップショットであり、各レンダリングで新しいバージョンのpropsを受け取ります。
- propsを変更することはできません。インタラクティブ性が必要な場合は、状態(state)を設定する必要があります。
Try out some challenges
Challenge 1 of 3:Extract a component #
This Gallery component contains some very similar markup for two profiles. Extract a Profile component out of it to reduce the duplication. You’ll need to choose what props to pass to it.
