propsはReactコンポーネントの入力です。親はJSXの属性として <UserCard name="Ada" online={true} /> のように渡し、子はそれを1つのオブジェクトとして受け取ります。通常は関数の引数で分割代入します。propsを使うと、1つのコンポーネントが使うたびに違うデータを表示できます。
同じ UserCard が3人の別々の人を描画しています。最後の1つに注目してください。値のない属性 online は online={true} を意味します。自分の名前と役割で4枚目のカードを追加してみてください。
propsを渡して読む
文字列は引用符で、それ以外の値は波かっこで渡します。数値、真偽値、配列、オブジェクト、関数、さらにはJSXも渡せます。
<Product
title="Desk lamp"
price={39.5}
inStock={false}
tags={['light', 'office']}
seller={{ name: 'Lumen', rating: 4.8 }}
/>
Reactはすべての属性を1つのオブジェクトにまとめ、コンポーネントの第1引数として渡します。props として読むこともできますし、必要なフィールドを引数リストの中で直接取り出すこともできます。
function Product(props) {
return <h3>{props.title}</h3>;
}
function Product({ title, price, seller }) {
return <h3>{title}, ${price} from {seller.name}</h3>;
}
どちらも同じオブジェクトを受け取ります。分割代入がよく使われるのは、関数のシグネチャを見ればコンポーネントが使うpropsが正確にわかるからです。
デフォルト値
JavaScriptの分割代入のデフォルト値 = value で、propにデフォルトを設定します。親がpropを省略したとき、または undefined を渡したときに使われます。null、0、false、'' は実際の値なので、このときは使われません。
最初の3つのボタンは、propがないか undefined の部分でデフォルト値を使います。最後のボタンは null を渡しているので、size は本当に null になり、対応するpaddingが見つかりません。size={null} を size="small" に変えると直ります。
古いコードでは静的プロパティ Button.defaultProps = { size: 'medium' } でデフォルトを設定します。React 19では関数コンポーネントの defaultProps が削除され、JSXは関数に設定されたそれを警告なしで無視します。クラスコンポーネントでは今も動きます。分割代入のデフォルト値を使ってください。
関数をpropsとして渡す
データは下へ流れます。親が子にpropsを渡し、その逆はありません。子が親に何かが起きたことを伝える必要があるときは、親が関数を渡し、子がそれを呼びます。慣習として、こうしたpropsには onSomething という名前を付けます。
Rating は何も保存しません。受け取った value を表示し、クリックを onRate で知らせるだけです。stateは App にあり、App がそれをまた下へ渡します。handleRate の代わりに onRate={setRating} を直接渡しても動きます。セッターも関数だからです。このようにstateを共通の親へ移すことをstateのリフトアップと呼びます。
propsのスプレッド
キーがコンポーネントのpropsと一致するオブジェクトがすでにあるなら、属性を1つずつ書く代わりに {...object} でスプレッドできます。引数リストではレスト構文が逆のことをします。いくつかのpropsを名前で取り出し、残りをまとめて転送するのです。
2つ目のアバターは person をスプレッドしてから color を設定しています。同じpropが2回現れると後のものが勝つので、上書きはスプレッドの後に書きます。TextField は label を自分で使い、type、placeholder、maxLength をそのまま <input> に渡します。スプレッドはこのようなラッパーに使いましょう。それ以外の場所では、propsを明示的に並べたほうがコンポーネントが何を受け取るかがわかりやすくなります。
propsは読み取り専用
コンポーネントは自分のpropsを決して変更してはいけません。propsは親のものであり、同じオブジェクトが共有されていることもあります。再代入が許されない関数の引数のように扱ってください。
function Counter({ count }) {
count = count + 1; // wrong: changes a local copy, the parent never sees it
return <p>{count}</p>;
}
function Profile(props) {
props.name = 'Someone else'; // wrong: in development React freezes props, so this throws a TypeError
return <p>{props.name}</p>;
}
それでもpropsは時間とともに変わります。親が新しい値でもう一度レンダリングすると、子は新しいpropsオブジェクトを受け取り、それでレンダリングします。
Temperature は celsius を一度も変えません。レンダリングのたびにそこから fahrenheit を計算します。スライダーを動かすと親のstateが変わるので、子は新しいpropを受け取ります。子が自分で変えられる値を必要とするなら、その値はpropではなくstateです。
propsとstateの違い
propsもstateも、コンポーネントが描画するものに影響する普通のJavaScriptの値で、どちらが変わってもコンポーネントは再レンダリングされます。違いは、その値を誰が持っているかです。
| props | state | |
|---|---|---|
| どこから来るか | 親から、JSXの属性として | コンポーネント自身から、useState や useReducer で |
| コンポーネントが変更できるか | いいえ、読み取り専用 | はい、セッターを通じて |
| 典型的な用途 | コンポーネントの設定:ラベル、サイズ、表示するデータ | 変わるものを覚えておく:入力テキスト、開いたメニュー |
同じ値が両方であることもよくあります。上の温度の例では、celsius は App ではstate、Temperature ではpropです。持ち主はそれをstateとして保持し、propとして下へ渡します。子が変更する必要があるときは、変更用の関数も一緒に渡します。
propにはJSXやコンポーネントも含めて、どんな値でも入れられます。icon={<StarIcon />} のように要素を渡せば、親が子の中の枠を埋められます。好きな名前を付けた children と同じ考え方です。
children prop
コンポーネントの開始タグと終了タグの間に書いたものは、すべて children という名前のpropとして届きます。カード、パネル、レイアウトのように、中身を事前に知らないラッパーはこうして作ります。
childrenのページでは、複数の枠を渡す方法と children を安全に扱う方法を紹介しています。
keyはpropsではない
key は属性のように見えますが、Reactがレンダリング間でリストの項目を対応させるために自分で使います。コンポーネントはそれを受け取りません。
コンソールには、props.key は undefined、props.id は実際の値と表示されます。子が識別子を必要とするなら、ここでの id のように、別の名前でもう一度渡してください。開発ビルドでは props.key を読むと警告も出ますが、プレビューは本番ビルドのように動くので、undefined しか見えません。
よくある質問
Reactのpropsとは何ですか?
props(propertiesの略)はコンポーネントの引数です。親はJSXの属性として <Avatar size={48} /> のように渡し、子はそれを1つのオブジェクトとして受け取ります。通常は function Avatar({ size }) のように分割代入します。
propにデフォルト値を設定するには?
分割代入のデフォルト値を使います:function Button({ size = 'medium' })。デフォルト値はpropが省略されたときか undefined のときに使われます。React 19では関数コンポーネントの defaultProps が削除されましたが、クラスコンポーネントでは今も使えます。
子コンポーネントは自分のpropsを変更できますか?
いいえ。propsは読み取り専用です。子の表示を変えたいときは親が新しいpropsを渡し、子から変更を求めたいときは親が onChange のような関数を渡して子がそれを呼びます。
propsとstateの違いは何ですか?
propsは親から来るもので、子は変更できません。stateはコンポーネント自身のもので、セッターを通じて変わります。ある値が、親ではstate、子ではpropsということもよくあります。
props.keyがundefinedになるのはなぜですか?
key は(古いReactの ref と同じく)React自身がリストの項目を追跡するために使い、コンポーネントには渡されません。子がその値を必要とするなら、<Row key={id} id={id} /> のように別の名前でもう一度渡してください。