3秒でわかる
React が描画できる値を表す TypeScript の型。children を受け取る props の型として使い、要素も文字列も配列も許可できます。
もう少し詳しく
どういうものか
React.ReactNode は、React が子要素として受け取って描画できる値をすべて含む型である。JSX 要素、文字列、数値、配列、フラグメント、そして何も描かないことを意味する null と undefined と boolean がここに入る。
React の型定義ではおおよそ次のように組まれている。
type ReactNode =
| ReactElement
| string
| number
| Iterable<ReactNode>
| boolean
| null
| undefined;<Card>テキストだけ</Card>
<Card><strong>要素</strong></Card>
<Card>{items.map((i) => <Row key={i.id} {...i} />)}</Card>
<Card>{count > 0 && <Badge n={count} />}</Card>これを ReactElement で受けると 1 つ目と 3 つ目と 4 つ目が型エラーになる。ReactNode は配列も条件式が返す false も含むので、上のすべてがそのまま通る。
具体例
type CardProps = {
title: string;
children: React.ReactNode; // 中身は何でも受ける
footer?: React.ReactNode; // 要素を props で渡す場合も同じ型
};
export function Card({ title, children, footer }: CardProps) {
return (
<section className="card">
<h2>{title}</h2>
<div>{children}</div>
{footer ? <div className="card-footer">{footer}</div> : null}
</section>
);
}
// 使う側
<Card title="売上" footer={<a href="/detail">詳細</a>}>
今月は 1,240 件でした。
</Card>;つまずきやすいところ
ReactNode を受け取った値に対して props や type を読もうとすると型エラーになる。ReactNode には文字列も null も含まれるので、要素として中身を触りたい場合は ReactElement を使うか、React.isValidElement() で絞り込む。
古い React では関数コンポーネントに React.FC を付けると children が自動で付いたが、React 18 の型定義からは外れた。children を受けるなら props の型に自分で書く。