Reactのコンポーネントは、互いに通信するためにpropsを使用します。すべての親コンポーネントは、子コンポーネントにpropsを与えることで、何らかの情報を渡すことができます。propsはHTMLの属性を連想させるかもしれませんが、オブジェクト、配列、関数など、任意のJavaScriptの値をpropsとして渡すことができます。
以下を学びます
- コンポーネントにpropsを渡す方法
- コンポーネントからpropsを読み取る方法
- propsのデフォルト値を指定する方法
- コンポーネントにJSXを渡す方法
- propsが時間の経過とともに変化する様子
よく知られたprops
propsは、JSXタグに渡す情報です。たとえば、className
、src
、alt
、width
、height
などは、<img>
に渡すことができるpropsの一部です。
function Avatar() { return ( <img className="avatar" src="https://i.imgur.com/1bX5QH6.jpg" alt="Lin Lanying" width={100} height={100} /> ); } export default function Profile() { return ( <Avatar /> ); }
<img>
タグに渡せるpropsは事前に定義されています(ReactDOMはHTML標準に準拠しています)。しかし、<Avatar>
のような独自のコンポーネントには、カスタマイズするために任意のpropsを渡すことができます。その方法はこちらです!
コンポーネントにpropsを渡す
このコードでは、Profile
コンポーネントは、子コンポーネントであるAvatar
にpropsを渡していません。
export default function Profile() {
return (
<Avatar />
);
}
2つのステップでAvatar
にpropsを与えることができます。
ステップ1:子コンポーネントにpropsを渡す
まず、Avatar
にpropsを渡します。たとえば、person
(オブジェクト)とsize
(数値)の2つのpropsを渡してみましょう。
export default function Profile() {
return (
<Avatar
person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }}
size={100}
/>
);
}
これで、これらのpropsをAvatar
コンポーネント内で読み取ることができます。
ステップ2:子コンポーネント内でpropsを読み取る
function Avatar
の直後の({
と})
の中に、コンマで区切られたperson, size
という名前をリストすることで、これらのpropsを読み取ることができます。これにより、変数を使用するのと同じように、Avatar
コード内でそれらを使用できます。
function Avatar({ person, size }) {
// person and size are available here
}
Avatar
に、person
とsize
propsをレンダリングに使用するロジックを追加すれば、完了です。
これで、Avatar
をさまざまなpropsを使って多様な方法でレンダリングできるように設定できます。値を調整してみてください!
import { getImageUrl } from './utils.js'; function Avatar({ person, size }) { return ( <img className="avatar" src={getImageUrl(person)} alt={person.name} width={size} height={size} /> ); } export default function Profile() { return ( <div> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> <Avatar size={80} person={{ name: 'Aklilu Lemma', imageId: 'OKS67lh' }} /> <Avatar size={50} person={{ name: 'Lin Lanying', imageId: '1bX5QH6' }} /> </div> ); }
Propsを使用すると、親コンポーネントと子コンポーネントを独立して考えることができます。たとえば、Profile
内で person
や size
のpropsを変更しても、Avatar
がそれらをどのように使用するかを考慮する必要はありません。同様に、Avatar
がこれらのpropsをどのように使用するかを、Profile
を見ることなく変更できます。
Propsは調整できる「つまみ」のように考えることができます。これらは、関数に対する引数と同じ役割を果たします。実際、propsはコンポーネントへの唯一の引数です! Reactコンポーネント関数は、単一の引数である props
オブジェクトを受け取ります。
function Avatar(props) {
let person = props.person;
let size = props.size;
// ...
}
通常、props
オブジェクト全体は必要ないので、個々のpropsに分割(destructure)します。
propsのデフォルト値の指定
値が指定されていない場合にフォールバックするデフォルト値をpropに指定したい場合は、分割代入を使用して、パラメータの直後に =
とデフォルト値を記述できます。
function Avatar({ person, size = 100 }) {
// ...
}
これで、<Avatar person={...} />
が size
propなしでレンダリングされると、size
は 100
に設定されます。
デフォルト値は、size
propがない場合、または size={undefined}
を渡した場合にのみ使用されます。ただし、size={null}
または size={0}
を渡すと、デフォルト値は使用されません。
JSXスプレッド構文によるpropsの転送
propsを渡すのが非常に反復的になる場合があります。
function Profile({ person, size, isSepia, thickBorder }) {
return (
<div className="card">
<Avatar
person={person}
size={size}
isSepia={isSepia}
thickBorder={thickBorder}
/>
</div>
);
}
反復的なコードに問題はありません。より読みやすい場合があります。ただし、簡潔さを重視する場合もあります。一部のコンポーネントは、この Profile
が Avatar
で行うように、すべてのpropsを子に転送します。それらはpropsを直接使用しないため、より簡潔な「スプレッド」構文を使用する方が理にかなっている場合があります。
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
これにより、各propsの名前をリストせずに、Profile
のすべてのpropsが Avatar
に転送されます。
スプレッド構文は控えめに使用してください。それを他のすべてのコンポーネントで使用している場合、何か問題があります。多くの場合、コンポーネントを分割し、子をJSXとして渡す必要があることを示しています。次のセクションで詳しく説明します!
JSXを子として渡す
組み込みブラウザタグをネストすることは一般的です。
<div>
<img />
</div>
同じように独自のコンポーネントをネストしたい場合があります。
<Card>
<Avatar />
</Card>
JSXタグ内にコンテンツをネストすると、親コンポーネントはそのコンテンツを children
というpropsで受け取ります。たとえば、以下の Card
コンポーネントは、<Avatar />
に設定された children
propを受け取り、ラッパーdivにレンダリングします。
import Avatar from './Avatar.js'; function Card({ children }) { return ( <div className="card"> {children} </div> ); } export default function Profile() { return ( <Card> <Avatar size={100} person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2' }} /> </Card> ); }
<Card>
内の <Avatar>
をテキストに置き換えて、Card
コンポーネントがどのようにネストされたコンテンツをラップできるかを確認してください。内部にレンダリングされるものを「知る」必要はありません。この柔軟なパターンを多くの場所で見ることができます。
children
propを持つコンポーネントは、親コンポーネントが任意のJSXで「埋める」ことができる「穴」を持っていると考えることができます。視覚的なラッパー(パネル、グリッドなど)には、children
propをよく使用します。

イラスト: レイチェル・リー・ネイバーズ
時間の経過に伴うpropsの変化
以下の Clock
コンポーネントは、親コンポーネントから color
と time
の2つのpropsを受け取ります。(親コンポーネントのコードは、まだ詳しく説明しない状態を使用しているため、省略されています。)
以下のセレクトボックスで色を変更してみてください。
export default function Clock({ color, time }) { return ( <h1 style={{ color: color }}> {time} </h1> ); }
この例は、コンポーネントが時間の経過とともに異なるpropsを受け取る可能性があることを示しています。propsは常に静的ではありません!ここでは、time
propは毎秒変化し、color
propは別の色を選択すると変化します。propsは、コンポーネントのデータを開始時だけでなく、任意の時点で反映します。
ただし、propsはイミュータブルです。これはコンピュータサイエンスの用語で、「変更不能」を意味します。コンポーネントがpropsを変更する必要がある場合(例えば、ユーザーの操作や新しいデータに応答する場合)、親コンポーネントに異なるpropsを渡すように「要求」する必要があります。それは新しいオブジェクトです!古いpropsは破棄され、最終的にJavaScriptエンジンがそれらが占有していたメモリを再利用します。
「propsを変更」しようとしないでください。ユーザーの入力に応答する必要がある場合(例えば、選択した色を変更する場合)、State: A Component’s Memory(ステート:コンポーネントの記憶)で学ぶことができる「ステートを設定」する必要があります。
まとめ
- propsを渡すには、HTML属性と同じようにJSXに追加します。
- propsを読み取るには、
function Avatar({ person, size })
の分割代入構文を使用します。 size = 100
のようにデフォルト値を指定できます。これは、propsが欠落している場合やundefined
の場合に使用されます。<Avatar {...props} />
JSXスプレッド構文を使用して、すべてのpropsを転送できますが、過度に使用しないでください!<Card><Avatar /></Card>
のようなネストされたJSXは、Card
コンポーネントのchildren
propとして表示されます。- propsは、時間の経過とともに読み取り専用のスナップショットです。すべてのレンダリングは、propsの新しいバージョンを受け取ります。
- propsを変更することはできません。インタラクティビティが必要な場合は、ステートを設定する必要があります。
チャレンジ 1の 3: コンポーネントを抽出する
このGallery
コンポーネントには、2つのプロファイルに対して非常に似たマークアップが含まれています。重複を減らすために、Profile
コンポーネントを抽出してください。どのpropsを渡すかを選択する必要があります。
import { getImageUrl } from './utils.js'; export default function Gallery() { return ( <div> <h1>Notable Scientists</h1> <section className="profile"> <h2>Maria Skłodowska-Curie</h2> <img className="avatar" src={getImageUrl('szV5sdG')} alt="Maria Skłodowska-Curie" width={70} height={70} /> <ul> <li> <b>Profession: </b> physicist and chemist </li> <li> <b>Awards: 4 </b> (Nobel Prize in Physics, Nobel Prize in Chemistry, Davy Medal, Matteucci Medal) </li> <li> <b>Discovered: </b> polonium (chemical element) </li> </ul> </section> <section className="profile"> <h2>Katsuko Saruhashi</h2> <img className="avatar" src={getImageUrl('YfeOqp2')} alt="Katsuko Saruhashi" width={70} height={70} /> <ul> <li> <b>Profession: </b> geochemist </li> <li> <b>Awards: 2 </b> (Miyake Prize for geochemistry, Tanaka Prize) </li> <li> <b>Discovered: </b> a method for measuring carbon dioxide in seawater </li> </ul> </section> </div> ); }