Part 2 · コンポーネントと props
props と型のつけ方
部品に情報を渡す。必須と任意の書き分け
前の章で作ったコンポーネントは、いつも同じものしか表示できませんでした。 同じ形で中身だけ違うものを出したいのに、これでは使い物になりません。
そこで、外から値を渡せるようにします。それが props です。
コンポーネントが関数なら、props はその引数です。 新しい概念ではありません。
props は関数の引数
値を渡すときは、HTML の属性と同じ書き方をします。
<Member name="さとう" role="デザイナー" />受け取る側では、これがひとつのオブジェクトとして届きます。
// 届いているもの
{ name: "さとう", role: "デザイナー" }オブジェクトで届くので、Part 0 でやった分割代入がそのまま使えます。React のコードがこの形をしているのはそのためです。
// 受け取るところで、直接取り出す
function Member({ name, role }: Props) {
return <p>{name}</p>;
}関数はひとつ、表示は 2 種類
さとう
デザイナー
すずき
役割は未設定
props-basic.tsx
// 受け取る値の形を決める
type Props = {
name: string;
// ? を付けた項目は、渡さなくてもよい
role?: string;
};
function Member({ name, role }: Props) {
return (
<div className="rounded-md border p-3">
<p className="font-semibold">{name}</p>
<p className="text-muted-foreground">{role ?? "役割は未設定"}</p>
</div>
);
}
export function PropsBasic() {
return (
<div className="flex flex-col gap-2.5">
<Member name="さとう" role="デザイナー" />
{/* role を渡さなくてもエラーにならない */}
<Member name="すずき" />
</div>
);
}受け取る値の形を決める
props に型を付けておくと、渡し忘れや打ち間違いをその場で教えてもらえます。
type Props = {
name: string; // 必ず渡す
role?: string; // 渡さなくてもよい
};nameを渡し忘れる → エラーになるnaneと打ち間違える → エラーになるname={123}と数値を渡す → エラーになる
どれも、動かす前に赤線が出ます。 型を書く手間より、これで助かる時間のほうがずっと大きくなります。
props-basic.tsx
// 受け取る値の形を決める
type Props = {
name: string;
// ? を付けた項目は、渡さなくてもよい
role?: string;
};
function Member({ name, role }: Props) {
return (
<div className="rounded-md border p-3">
<p className="font-semibold">{name}</p>
<p className="text-muted-foreground">{role ?? "役割は未設定"}</p>
</div>
);
}
export function PropsBasic() {
return (
<div className="flex flex-col gap-2.5">
<Member name="さとう" role="デザイナー" />
{/* role を渡さなくてもエラーにならない */}
<Member name="すずき" />
</div>
);
}渡されなかったときの値を決めておく
?? を毎回書く代わりに、 受け取るところで初期値を決めておくこともできます。
function Badge({ label, tone = "normal" }: Props) {tone が渡されなかったときは "normal" になります。これも React の機能ではなく、 JavaScript の分割代入がもともと持っている書き方です。
tone を渡さないほうは normal になっている
受け取る値を絞る
このデモでは、tone の型を "normal" | "warning" にしています。 Part 0 でやった union です。
こうしておくと、tone="warn" のような打ち間違いがエラーになります。渡せる値そのものを制限してしまうのが、 props に型を付ける最大の効果です。
props-default.tsx
type Props = {
label: string;
// 決まった値のどれか、しか受け取らないようにする
tone?: "normal" | "warning";
};
// 受け取るところで = を書くと、渡されなかったときの値になる
function Badge({ label, tone = "normal" }: Props) {
return (
<span
className={
tone === "warning"
? "rounded border border-amber-500 px-2 py-0.5 text-amber-700"
: "rounded border px-2 py-0.5 text-muted-foreground"
}
>
{label}
</span>
);
}
export function PropsDefault() {
return (
<div className="flex flex-wrap gap-2.5">
<Badge label="通常" />
<Badge label="注意" tone="warning" />
</div>
);
}渡し方のこまごまとした話
// 文字列はそのまま書ける
<Member name="さとう" />
// それ以外は波括弧に入れる
<Member age={20} tags={["a", "b"]} onSave={handleSave} />
// 値が true のときは、名前だけでよい
<Member isAdmin /> // isAdmin={true} と同じ文字列以外を渡すときに波括弧が要るのは、そこから先が JavaScript だからです。 JSX の章でやった「波括弧の中は JavaScript に戻る」と同じ話です。
props-basic.tsx
// 受け取る値の形を決める
type Props = {
name: string;
// ? を付けた項目は、渡さなくてもよい
role?: string;
};
function Member({ name, role }: Props) {
return (
<div className="rounded-md border p-3">
<p className="font-semibold">{name}</p>
<p className="text-muted-foreground">{role ?? "役割は未設定"}</p>
</div>
);
}
export function PropsBasic() {
return (
<div className="flex flex-col gap-2.5">
<Member name="さとう" role="デザイナー" />
{/* role を渡さなくてもエラーにならない */}
<Member name="すずき" />
</div>
);
}理解できたか確かめる
確認クイズ
props はコンポーネントに何として届く?
確認クイズ
type Props = { tone?: 'normal' | 'warning' } と書く利点は?
props-basic.tsx
// 受け取る値の形を決める
type Props = {
name: string;
// ? を付けた項目は、渡さなくてもよい
role?: string;
};
function Member({ name, role }: Props) {
return (
<div className="rounded-md border p-3">
<p className="font-semibold">{name}</p>
<p className="text-muted-foreground">{role ?? "役割は未設定"}</p>
</div>
);
}
export function PropsBasic() {
return (
<div className="flex flex-col gap-2.5">
<Member name="さとう" role="デザイナー" />
{/* role を渡さなくてもエラーにならない */}
<Member name="すずき" />
</div>
);
}この章のまとめ
- props はコンポーネント(関数)の引数
- いくつ書いても、届くのはひとつのオブジェクト
- 型を付けると、渡し忘れ・打ち間違い・型違いが動かす前に分かる
?は任意の項目。ないときの表示も用意しておく{ tone = "normal" }で初期値を決められる
props-basic.tsx
// 受け取る値の形を決める
type Props = {
name: string;
// ? を付けた項目は、渡さなくてもよい
role?: string;
};
function Member({ name, role }: Props) {
return (
<div className="rounded-md border p-3">
<p className="font-semibold">{name}</p>
<p className="text-muted-foreground">{role ?? "役割は未設定"}</p>
</div>
);
}
export function PropsBasic() {
return (
<div className="flex flex-col gap-2.5">
<Member name="さとう" role="デザイナー" />
{/* role を渡さなくてもエラーにならない */}
<Member name="すずき" />
</div>
);
}