- React
React propsの渡し方とchildrenの使い方|TS型定義
propsとは、親コンポーネントから子コンポーネントへ値を渡すための引数で、JSXの属性として書いた値が1つのオブジェクトにまとまって子の関数に届きます。 タグの間に書いた中身は children という名前のpropsとして届きます。文字列はクォートで、それ以外の値(数値・真偽値・関数・オブジェクト)は波かっこで渡す、というのが基本の形です。
この記事では、値の種類ごとの渡し方を「親の書き方」と「子の受け取り方」のペアで一覧にし、childrenの型(ReactNode・PropsWithChildren・React.FC)の違い、デフォルト値の付け方、よく出る型エラーの文面と直し方までをまとめます。掲載したコードと出力は、React 19.3.0 と TypeScript 7.0.2 で動かして確かめたものです。
propsの渡し方の早見表
| 渡すもの | 親の書き方 | 子の型の書き方 | ひとこと |
|---|---|---|---|
| 文字列 | name="ノート" |
name: string |
クォートで囲む。変数なら name={title} |
| 数値 | price={120} |
price: number |
波かっこが必要。price="120" は文字列になる |
| 真偽値 | soldOut または soldOut={false} |
soldOut: boolean |
名前だけ書くと true |
| オブジェクト | user={{ id: 1, name: "佐藤" }} |
user: User |
外側が「JSの値」、内側が「オブジェクト」の波かっこ |
| 配列 | tags={["管理者", "東京"]} |
tags: string[] |
変数を渡すなら tags={tags} |
| 関数 | onAdd={(n) => setTotal(n)} |
onAdd: (amount: number) => void |
呼び出さずに関数そのものを渡す |
| children | タグの間に中身を書く | children: ReactNode |
文字列・要素・複数要素をまとめて受け取れる |
| まとめて渡す | {...item} |
個別のpropsと同じ | オブジェクトのキーがそのままpropsになる |
| 省略できるprops | 書かない | size?: number と { size = 14 } |
分割代入でデフォルト値を付ける |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「React propsの渡し方とchildrenの使い方|TS型定義」
この記事の確認環境
| 項目 | バージョン |
|---|---|
| React / react-dom | 19.3.0(開発ビルド) |
| @types/react / @types/react-dom | 19.3.0 |
| TypeScript | 7.0.2(tsc --noEmit、strict) |
| 実行 | Node.js 22.22.2、jsdom 30.1.1、JSXの変換は esbuild 0.28.2 |
HTMLの出力は react-dom/server の renderToStaticMarkup で、クリックの動きは jsdom 上で createRoot を使って確かめました。実際のブラウザでの表示確認は未実行です。型エラーの文面は tsc の出力から、ファイル名と行番号を省いて載せています。
propsの基本:親が属性で渡し、子が引数で受け取る
propsの流れは一方向です。親がJSXの属性として書いた値が、子の関数の第1引数に1つのオブジェクトとして届きます。 子の側では、引数を分割代入で受け取る書き方が一般的です。
// 子:受け取る側。型を先に決めて、引数を分割代入する
type GreetingProps = { name: string };
function Greeting({ name }: GreetingProps) {
return <p>こんにちは、{name}さん</p>;
}
// 親:渡す側。属性として書く
function App() {
return <Greeting name="佐藤" />;
}
覚えておきたい性質は次の3つです。
| 性質 | 内容 |
|---|---|
| 向きは親から子へ | 子から親へ値を返したいときは、親から関数を渡して子に呼んでもらう |
| 読み取り専用 | 子の中でpropsを書き換えない。変化する値は親のstateで持つ |
| 再レンダリングのたびに新しい値 | 親が再レンダリングされると、その時点のpropsが子に渡り直る |
読み取り専用であることは、動かして確かめられます。子の中で props.name = "x" と代入したところ、開発ビルドでは次のエラーになりました。
Cannot assign to read only property 'name' of object '#<Object>'
値の種類ごとの渡し方(親子ペアのコード)
ここからは、値の種類ごとに「子の定義」と「親からの渡し方」を並べます。どれもそのまま貼って動かせる形です。
文字列・数値・真偽値を渡す
type ItemProps = { name: string; price: number; soldOut: boolean };
// 子
function Item({ name, price, soldOut }: ItemProps) {
return (
<li>
{name}: {price}円{soldOut && "(品切れ)"}
</li>
);
}
// 親
function ItemList() {
return (
<ul>
<Item name="ノート" price={120} soldOut />
<Item name="ペン" price={80} soldOut={false} />
</ul>
);
}
実行結果(出力されたHTML)は次のとおりです。
<ul><li>ノート: 120円(品切れ)</li><li>ペン: 80円</li></ul>
ポイントは3つあります。
- 文字列だけがクォートで書けます。 数値を
price="120"と書くと文字列として渡り、型エラー(後述のTS2322)になります。 - 真偽値は名前だけ書くと true になります。false を渡したいときは
soldOut={false}と書きます。 - 変数や計算結果を渡すときは、型に関係なく波かっこを使います(
name={item.name}、price={base * 1.1})。
オブジェクト・配列を渡す
type User = { id: number; name: string };
type UserCardProps = { user: User; tags: string[] };
// 子
function UserCard({ user, tags }: UserCardProps) {
return (
<p>
{user.id}:{user.name} [{tags.join(",")}]
</p>
);
}
// 親
function Page() {
return <UserCard user={{ id: 1, name: "佐藤" }} tags={["管理者", "東京"]} />;
}
<p>1:佐藤 [管理者,東京]</p>
user={{ ... }} の波かっこが二重になるのは、外側が「ここからJavaScriptの値」という印、内側がオブジェクトそのものだからです。特別な記法ではありません。すでに変数に入っているなら user={currentUser} と一重で書けます。
関数を渡す(子から親へ知らせる)
子で起きた出来事を親に伝えるには、親から関数を渡します。子は受け取った関数を呼ぶだけで、状態は親が持つという分担になります。
import { useState } from "react";
type AddButtonProps = { onAdd: (amount: number) => void };
// 子:押されたら、受け取った関数を呼ぶ
function AddButton({ onAdd }: AddButtonProps) {
return <button onClick={() => onAdd(5)}>+5</button>;
}
// 親:状態を持ち、更新する関数を渡す
function Counter() {
const [total, setTotal] = useState(0);
return (
<div>
<output>{total}</output>
<AddButton onAdd={(n) => setTotal((t) => t + n)} />
</div>
);
}
ボタンを2回クリックしたあとの表示を確かめた結果です。
2回クリック後の output: 10
関数を渡すときに気を付けたいのは、呼び出した結果ではなく関数そのものを渡すことです。
| 書き方 | 渡るもの | 動き |
|---|---|---|
onAdd={handleAdd} |
関数 | クリックされたときに呼ばれる |
onAdd={(n) => handleAdd(n)} |
関数 | 引数を加工したいときに使う |
onAdd={handleAdd()} |
戻り値 | 描画のたびに実行されてしまう |
関数型の書き方は (引数名: 型) => 戻り値の型 です。戻り値を使わないなら void にします。
childrenを渡す(タグの間に書く)
開始タグと終了タグの間に書いた中身は、children という名前のpropsとして子に届きます。 枠・カード・レイアウトのように「中身は使う側が決める」部品に向いています。
import type { ReactNode } from "react";
type PanelProps = { title: string; children: ReactNode };
// 子:受け取った children を置きたい場所に書く
function Panel({ title, children }: PanelProps) {
return (
<section>
<h2>{title}</h2>
{children}
</section>
);
}
// 親:タグの間に中身を書く
function Home() {
return (
<Panel title="お知らせ">
<p>本文です</p>
</Panel>
);
}
<section><h2>お知らせ</h2><p>本文です</p></section>
childrenは特別扱いに見えますが、<Panel title="お知らせ" children={<p>本文です</p>} /> と属性で書いたのと同じ意味です。読みやすさのため、通常はタグの間に書きます。
オブジェクトをまとめて渡す(スプレッド)
渡したい値がすでにオブジェクトにまとまっているなら、{...obj} で展開できます。
const item = { name: "ノート", price: 120, soldOut: false };
// <Item name="ノート" price={120} soldOut={false} /> と同じ
const element = <Item {...item} />;
<li>ノート: 120円</li>
便利な一方で、どのpropsが渡っているかがコード上で見えにくくなります。渡す値が3つ程度までなら個別に書く、同じ形のオブジェクトをそのまま流すならスプレッド、と使い分けると読みやすさを保てます。
画面に表示される値・されない値
JSXの中に値を置いたとき、すべてが文字として表示されるわけではありません。次のコードを動かして確かめました。
<p>{true}{false}{null}{undefined}{0}{""}|{0 && "x"}|{[].length && "y"}</p>
<p>0|0|0</p>
| 値 | 表示 |
|---|---|
| true / false / null / undefined | 何も表示されない |
| 空文字 | 何も表示されない |
| 数値の 0 | 0 と表示される |
| 文字列・数値 | そのまま表示される |
件数 && ... の形で条件表示をすると、件数が 0 のときに 0 が表示されます。 items.length > 0 && ... のように真偽値にしてから使うと、意図どおり何も表示されません。
childrenの型:ReactNode・PropsWithChildren・React.FCの違い
childrenの型の候補はいくつかあります。迷ったら children: ReactNode を自分で書くのが、いちばん読みやすく融通の利く選択です。
比較表
| 書き方 | 受け取れる中身 | childrenの必須・任意 | 向いている場面 |
|---|---|---|---|
children: ReactNode |
文字列・数値・要素・配列・null・真偽値など表示できるもの全般 | 必須(children?: にすれば任意) |
通常はこれ |
PropsWithChildren<Props> |
ReactNode と同じ | 任意(children?: ReactNode が足される) |
既存のProps型にchildrenを足したいとき |
children: ReactElement |
JSXの要素1つだけ | 必須 | 「必ず要素を1つ」と絞りたいとき |
children: JSX.Element |
ReactElement とほぼ同じ | 必須 | ReactElementと同じ用途 |
children: (value: T) => ReactNode |
関数 | 必須 | 子が持つ値を使って親が描画を決めるとき |
React.FC<Props> |
Propsに書いたものだけ | childrenは自動では付かない | 関数全体に型を付けたいとき |
受け取れる中身を tsc で確かめる
children: ReactNode の部品に、いろいろな中身を渡して型チェックを通しました。次の書き方はすべてエラーなしです。
import type { ReactNode } from "react";
type BoxProps = { children: ReactNode };
function Box({ children }: BoxProps) {
return <div>{children}</div>;
}
const samples = [
<Box>text</Box>,
<Box>{1}</Box>,
<Box>{null}</Box>,
<Box>{false}</Box>,
<Box>{undefined}</Box>,
<Box><b>a</b><b>b</b></Box>,
<Box>{[<i key="1">x</i>]}</Box>,
];
{undefined} や {null} を明示的に書いた場合は「childrenを渡した」扱いになり、必須でも通ります。タグの間を空にしたとき(<Box /> や <Box></Box>)だけが「渡していない」扱いです。
実行時に children に入っている値
型とは別に、実行時に children へ何が入るかも確かめました。typeof と Array.isArray で種類を表示する部品に、中身を変えて渡した結果です。
| 親の書き方 | children の中身 |
|---|---|
<Show /> |
undefined |
<Show>text</Show> |
string |
<Show>{3}</Show> |
number |
<Show><b>a</b></Show> |
object(要素1つ) |
<Show><b>a</b><b>b</b></Show> |
配列(長さ2) |
<Show>{null}</Show> |
null |
<Show>a{1}</Show> |
配列(長さ2) |
中身が1つなら単体、2つ以上なら配列になるため、children を自分で map しようとすると場合分けが必要になります。そのまま {children} と置くだけなら、どの形でもReactが正しく描画します。
PropsWithChildrenの使いどころ
PropsWithChildren は、渡した型に children?: ReactNode を足すだけの型です。
import type { PropsWithChildren } from "react";
type CardProps = PropsWithChildren<{ title: string }>;
function Card({ title, children }: CardProps) {
return <div>{title}{children}</div>;
}
// children が任意なので、どちらも通る
const a = <Card title="a" />;
const b = <Card title="a">x</Card>;
childrenが任意になる点が children: ReactNode との違いです。「中身を必ず書いてほしい」部品では children: ReactNode を自分で書き、「中身はあってもなくてもよい」部品では PropsWithChildren か children?: ReactNode を選ぶと、型が意図を表してくれます。
React.FCとchildrenの関係
React.FC(FunctionComponent)は、関数コンポーネント全体に付ける型です。React 17 までの型定義では React.FC を使うと children が自動で受け取れましたが、@types/react 18 以降は自動では付かなくなり、children を使うならPropsに自分で書く形になりました(18での変更は一般に知られた仕様で、今回は 19.3.0 の型定義で動きを確かめています)。
import type { FC } from "react";
type BadgeProps = { label: string };
const Badge: FC<BadgeProps> = ({ label }) => <span>{label}</span>;
const element = <Badge label="new">text</Badge>;
error TS2322: Type '{ label: string; children: string; }' is not assignable to type 'IntrinsicAttributes & BadgeProps'.
Property 'children' does not exist on type 'IntrinsicAttributes & BadgeProps'.
直し方は、Propsにchildrenを足すだけです。
type BadgeProps = { label: string; children: ReactNode };
// または
const Badge: FC<PropsWithChildren<{ label: string }>> = ({ label, children }) => (
<span>{label}{children}</span>
);
React.FC を使う書き方と、引数に型を付ける書き方のどちらでも動きます。違いを表にまとめます。
| 観点 | 引数に型を付ける function A({ x }: Props) |
const A: FC<Props> = ... |
|---|---|---|
| children | Propsに書いたときだけ受け取れる | 同じ(18以降) |
| ジェネリクス | function List<T>(props: ListProps<T>) と書ける |
書きにくい |
| 記述量 | 少ない | 型注釈が1つ増える |
| 関数全体の型 | 戻り値は推論される | 戻り値の型もチェックされる |
どちらかに統一されていれば十分です。新しく書くなら、記述が少なくジェネリクスにも対応しやすい「引数に型を付ける」形が扱いやすいでしょう。
デフォルト値の付け方:分割代入で書く
省略できるpropsには、型で ? を付け、分割代入でデフォルト値を書きます。
type LabelProps = { text?: string | null; size?: number };
function Label({ text = "未設定", size = 14 }: LabelProps) {
return <span style={{ fontSize: size }}>{String(text)}</span>;
}
デフォルト値が使われる条件
デフォルト値が使われるのは、propsを書かなかったときと undefined を渡したときだけです。null・空文字・0 は「値を渡した」扱いになります。上の Label で確かめた結果です。
| 親の書き方 | 出力 | デフォルト値 |
|---|---|---|
<Label /> |
<span style="font-size:14px">未設定</span> |
使われる |
<Label text={undefined} /> |
<span style="font-size:14px">未設定</span> |
使われる |
<Label text={null} /> |
<span style="font-size:14px">null</span> |
使われない |
<Label text="" size={0} /> |
<span style="font-size:0"></span> |
使われない |
APIの応答などで null が入ってくる可能性があるなら、text ?? "未設定" のように本体側で補うと、null と undefined の両方をまとめて扱えます。
defaultPropsは関数コンポーネントでは使われない
以前は Heading.defaultProps = { ... } という書き方がありました。React公式のReact 19アップグレードガイドには、関数コンポーネントの defaultProps を取り除き、ES6のデフォルト引数に置き換えると書かれています(今回ページを開いて確認しました)。React 19.3.0 で動かした結果は次のとおりです。
function Heading({ text }: { text?: string }) {
return <h1>{String(text)}</h1>;
}
Heading.defaultProps = { text: "Hello" };
// <Heading /> を描画
<h1>undefined</h1>
defaultProps の値は使われず、コンソールへの警告も出ませんでした。 エラーにならないぶん気付きにくいので、React 19 へ上げるときは defaultProps を検索して分割代入へ置き換えておくと安心です。
型の面では、書き方によって結果が分かれました。
| 書き方 | tsc の結果 |
|---|---|
function Heading(...) {} に Heading.defaultProps = ... |
エラーにならない(関数へのプロパティ追加として通る) |
const Heading: FC<Props> = ... に Heading.defaultProps = ... |
error TS2339: Property 'defaultProps' does not exist on type 'FC<HProps>'. |
置き換え後の形はこうなります。
type HeadingProps = { text?: string };
function Heading({ text = "Hello" }: HeadingProps) {
return <h1>{text}</h1>;
}
デフォルト値にオブジェクトや配列を使うとき
{ items = [] } のように書くと、描画のたびに新しい配列が作られます。 そのまま表示に使うだけなら問題ありませんが、useEffect の依存配列や memo 化した子に渡すと「毎回変わった」と判定されます。コンポーネントの外に定数として置くと、同じ参照を使い回せます。
const EMPTY: string[] = [];
function TagList({ tags = EMPTY }: { tags?: string[] }) {
return <ul>{tags.map((t) => <li key={t}>{t}</li>)}</ul>;
}
よく出る型エラーの文面と直し方
propsまわりで見かける型エラーを、実際のtscの文面とあわせて整理します。まず一覧です。
| コード | 文面の要点 | 原因 | 直し方 |
|---|---|---|---|
| TS2741 | Property 'count' is missing ... but required | 必須のpropsを渡していない | 渡す、または型を count?: にしてデフォルト値を付ける |
| TS2322 | Type 'string' is not assignable to type 'number' | 型が違う(count="3" など) |
count={3} と波かっこで渡す |
| TS2322 | Property 'color' does not exist on type 'IntrinsicAttributes & ...' | 型にないpropsを渡した | Propsに追加する、または渡すのをやめる |
| TS2322 | Property 'children' does not exist on type ... | childrenを型に書いていない | children: ReactNode を足す |
| TS2741 | Property 'children' is missing | childrenが必須なのに中身が空 | 中身を書く、または children?: にする |
| TS2747 | components don't accept text as child elements | children: ReactElement に文字列を渡した |
型を ReactNode にする、または要素で包む |
| TS2746 | expects a single child ... but multiple children were provided | 要素1つの型に複数渡した | 型を ReactNode にする、またはFragmentで1つにまとめる |
| TS2322 | Types of parameters 'id' and 'id' are incompatible | 関数propsの引数の型が合わない | 子の定義に合わせて引数の型を直す |
| TS2339 | Property 'defaultProps' does not exist on type 'FC<...>' | FC型に defaultProps を書いた | 分割代入のデフォルト値に置き換える |
以下は、次の Card を使って再現したものです。
type CardProps = { title: string; count: number; children: ReactNode };
function Card({ title, count, children }: CardProps) {
return <section><h2>{title}({count})</h2>{children}</section>;
}
必須のpropsを渡していない(TS2741)
const e1 = <Card title="A">x</Card>;
error TS2741: Property 'count' is missing in type '{ title: string; children: string; }' but required in type 'CardProps'.
文面の前半に「いま渡しているpropsの形」、後半に「足りない名前」が出ます。渡すのが正しいなら count={0} を足し、省略できてよい値なら型を count?: number にしてデフォルト値を付けます。
型が違う(TS2322)
const e2 = <Card title="A" count="3">x</Card>;
error TS2322: Type 'string' is not assignable to type 'number'.
数値をクォートで書いたときの典型です。count={3} に直します。フォームの入力値のように元が文字列なら、count={Number(value)} と変換してから渡します。
型にないpropsを渡した(TS2322)
const e3 = <Card title="A" count={3} color="red">x</Card>;
error TS2322: Type '{ title: string; count: number; color: string; children: string; }' is not assignable to type 'IntrinsicAttributes & CardProps'.
Property 'color' does not exist on type 'IntrinsicAttributes & CardProps'.
2行目の Property 'color' does not exist が要点です。綴りの違い(classname と className など)でも同じ文面になります。IntrinsicAttributes は key のようにReactが予約している属性の型で、読み飛ばして構いません。
childrenが必須なのに中身がない(TS2741)
const e4 = <Card title="A" count={3} />;
error TS2741: Property 'children' is missing in type '{ title: string; count: number; }' but required in type 'CardProps'.
要素1つの型に文字列・複数要素を渡した(TS2747・TS2746)
type WrapProps = { children: ReactElement };
function Wrap({ children }: WrapProps) {
return <div>{children}</div>;
}
const e7 = <Wrap>text</Wrap>;
const e8 = <Wrap><b>a</b><b>b</b></Wrap>;
error TS2747: 'Wrap' components don't accept text as child elements. Text in JSX has the type 'string', but the expected type of 'children' is 'ReactElement<unknown, string | JSXElementConstructor<any>>'.
error TS2746: This JSX tag's 'children' prop expects a single child of type 'ReactElement<unknown, string | JSXElementConstructor<any>>', but multiple children were provided.
ReactElement は「JSXの要素1つ」だけを表します。文字列や複数要素も受けたいなら ReactNode に変えるのが近道です。
関数propsの引数の型が合わない(TS2322)
type BtnProps = { onSelect: (id: number) => void };
function Btn({ onSelect }: BtnProps) {
return <button onClick={() => onSelect(1)}>go</button>;
}
const e9 = <Btn onSelect={(id: string) => console.log(id)} />;
error TS2322: Type '(id: string) => void' is not assignable to type '(id: number) => void'.
Types of parameters 'id' and 'id' are incompatible.
Type 'number' is not assignable to type 'string'.
子は number を渡してくるのに、親の関数は string を待っている、という食い違いです。親側の引数の型注釈を外せば子の定義から推論されるので、onSelect={(id) => ...} と書くのがいちばん簡単です。
応用:よく使う型の書き方
HTML要素のpropsを引き継ぐ(ComponentProps)
ボタンや入力欄を包む部品では、元の要素が持つ属性(type、disabled、onClick など)をまとめて受け取りたくなります。ComponentProps<"button"> を使うと、1つずつ書かずに済みます。
import type { ComponentProps } from "react";
type ButtonProps = ComponentProps<"button"> & { variant?: "primary" | "ghost" };
function Button({ variant = "primary", ...rest }: ButtonProps) {
return <button data-variant={variant} {...rest} />;
}
// 元のbuttonの属性もchildrenもそのまま使える
const element = (
<Button type="submit" disabled onClick={(e) => e.currentTarget.blur()}>
送信
</Button>
);
このコードは tsc でエラーなしを確認しています。...rest で「自分で使うprops以外」をまとめ、内側の要素へスプレッドするのが定番の形です。
選択肢を絞る(文字列のユニオン型)
variant?: "primary" | "ghost" のように文字列を並べると、渡せる値が候補に絞られ、エディタの補完にも出ます。 string より安全で、書く側にも親切です。
描画内容を関数で受け取る
子が持っている値を使って、親が表示を決めたい場合は、関数をpropsやchildrenとして渡します。
type CounterViewProps = {
render: (n: number) => ReactNode;
children: (n: number) => ReactNode;
};
function CounterView({ render, children }: CounterViewProps) {
return <div>{render(1)}{children(2)}</div>;
}
const element = (
<CounterView render={(n) => <b>{n}</b>}>
{(n) => <i>{n}</i>}
</CounterView>
);
childrenに関数を渡す形は、タグの間に {(n) => ...} と書きます。型は (n: number) => ReactNode です。
keyとrefは少し特別
| 名前 | 子の中で読めるか | 補足 |
|---|---|---|
| key | 読めない | リストの識別用。同じ値を子で使いたいなら別名(id など)でも渡す |
| ref | React 19 から通常のpropsとして読める | DOM要素を親から触りたいときに使う |
props.key を子の中で読んだところ、値は undefined で、開発ビルドでは次の警告が出ました。
K: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)
propsを設計するときのチェックリスト
| 確認すること | 目安 |
|---|---|
| 必須と任意が型で分かれているか | 任意には ? を付け、分割代入でデフォルト値を書く |
| 数値・真偽値を波かっこで渡しているか | クォートは文字列だけ |
| 関数は「そのもの」を渡しているか | onClick={handle}。handle() と書かない |
| childrenの型は意図に合っているか | 通常は ReactNode。任意なら children?: |
| nullが来る可能性のある値か | デフォルト値は undefined にしか効かないので ?? で補う |
| defaultProps が残っていないか | React 19 では使われないため分割代入へ |
| propsの数が増えすぎていないか | 関連する値はオブジェクトにまとめる、または children で中身を渡す |
よくある質問
Q. propsとstateはどう使い分けますか? A. 親から受け取って読むだけの値がprops、コンポーネント自身が持って更新する値がstateです。子でpropsを変えたくなったら、親のstateを更新する関数をpropsで受け取り、それを呼ぶ形にします。
Q. children の型は ReactNode と ReactElement のどちらがよいですか? A. 通常は ReactNode です。文字列・数値・複数要素・null まで受け取れます。「要素を必ず1つだけ」と制限したいときに ReactElement を選びます。今回の確認でも、ReactElement に文字列を渡すとTS2747、複数要素を渡すとTS2746になりました。
Q. React.FC は使ってよいですか? A. 使えます。ただし @types/react 18 以降は children が自動で付かないので、必要ならPropsに書きます。チーム内でどちらかに揃っていれば問題ありません。
Q. 孫コンポーネントまでpropsを何段も渡すのが大変です。 A. まず children で中身ごと渡す形にできないか考えると、中継するpropsが減ることがあります。それでも広い範囲で共有したい値は、Context や状態管理ライブラリの利用を検討します。
まとめ
- 文字列はクォート、それ以外は波かっこで渡す。真偽値は名前だけ書くと true
- 関数は呼び出さずにそのまま渡す。子から親へ知らせる手段になる
- タグの間の中身は children として届く。型は基本
children: ReactNode - PropsWithChildren は children を任意で足す型、React.FC は18以降 children を自動では持たない
- デフォルト値は分割代入で書く。効くのは省略時と undefined のときだけで、null・0・空文字には効かない
- defaultProps は React 19 の関数コンポーネントでは使われない(19.3.0で警告なしに無視されることを確認)
- 型エラーは TS2741(不足)・TS2322(型違い・余分)・TS2747/TS2746(childrenの形) の文面を覚えると直しやすい
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「React propsの渡し方とchildrenの使い方|TS型定義」
株式会社RJCでは、Reactのpropsとchildrenの型の付け方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。