Reactのコードの中に「children」が出てきたけどコレって何!?と感じていませんか?
children は、コンポーネントの再利用性を高める、Reactの核心となる仕組みの一つです。childrenを理解すれば、あなたのコンポーネント設計スキルは格段に向上します。
本記事では、childrenがどのように機能するのか、分割代入を使った場合はどのような記述になるのかなど実際のコード例を交えながら、その基本から仕組みまでを解説しています。
childrenとは何か?
Reactにおけるchildren(チルドレン)は、コンポーネントの開始タグと終了タグの間に記述された内容を、そのコンポーネント内部で受け取って表示するための特別なprops(プロパティ)です。
通常のpropsがコンポーネントにデータ(文字列、数値、関数など)を渡すのに対し、childrenはJSXの要素やコンポーネントそのものを「中身」として渡す、柔軟なレイアウト構造を作る仕組みです。
Reactのpropsとは何か?については下記をご参考ください。
childrenの基本と仕組み
Reactコンポーネントを「箱」や「枠組み」と見立てた場合、childrenはその「箱の中に自由に入れられる中身」の役割を果たします。
例えば、以下のようなCardコンポーネントがあるとします。
expoert default function Card(props) {
return (
<div className="card-wrapper">
{props.children}
</div>
);props.childrenをdivタグの中に記述しています。つまり、親コンポーネントから渡された何らかのデータを表示するということです。
親コンポーネントで、上記のCardコンポーネントを呼び出し、その中にh2タグとpタグを記載したとします。
import Card from './Card.jsx'
<Card>
<h2>商品タイトル</h2>
<p>商品の説明文です。</p>
</Card>
すると、このh2タグとpタグが、Cardコンポーネントのprops.childrenに表示されます。
最終的なHTMLは以下のようになります。
<div className="card-wrapper">
<h2>商品タイトル</h2>
<p>商品の説明文です。</p>
</div>
コンポーネント内の「children」がある場合は、親から渡されたタグなどのデータを表示するということ。
分割代入による記述 {children}
childrenを呼び出すときにドットをつけてプロパティを指定するのではなく、直接 {children} が書かれている場合もあります。
これは分割代入という書き方を使い、上記のprops.childrenをより省略したものです。
expoert default function Card({ children }) {
return (
<div className="card-wrapper">
{children}
</div>
);
}分割代入とは何か?については下記をご参考ください。
【JavaScript】分割代入とは何か?(変数名を変える方法(変更),必要なデータだけ取り出す, デフォルト値, 多次元/ネストしたデータ)
childrenの注意点
childrenは特別なprops
childrenは、通常のpropsと同じように扱えますが、コンポーネントタグに囲まれた内容が自動的に渡されるという点で特別です。
対象のコンポーネントを呼び出すときにchildren={…}と記述する必要はありません。
型は保証されていない
childrenとして渡される要素は、テキスト、単一のHTML要素、複数のコンポーネント、またはそれらの配列など、様々な型になり得ます。
- 単一の要素/テキスト
単一のオブジェクトまたは文字列になる。 - 複数の要素
配列のような構造になる。
Childrenは単一要素にもなり得ます。このため、配列であると仮定して処理(例: children.map())するのは危険です。
※childrenを処理したり、ループで回したり、数を数えたりしたい場合は、Reactが提供するReact.Childrenを使うことが推奨です。
React.Children.map(children, (child, index) => ...)何もない場合はundefinedになる
childrenを含むコンポーネントが呼び出されたときに、そのコンポーネントタグの開始タグと終了タグの間で何も渡されない場合は「undefined」になります。
childrenの実例1:汎用的なラッパーコンポーネント
モーダル(ダイアログ)は、「背景と閉じるボタンなどの共通の枠組み」の中に、「ページごとに異なる内容」を入れる代表的な例です。
function Modal({ title, isOpen, onClose, children }) {
if (!isOpen) return null; // isOpenがfalseなら何も表示しない
return (
<div className="modal-backdrop">
<div className="modal-content">
<header>
<h3>{title}</h3>
<button onClick={onClose}>閉じる</button>
</header>
<div className="modal-body">
{children}
</div>
</div>
</div>
);
}呼び出し側(親コンポーネント)では、モーダルの中身を自由に記述できます。Modalの開始タグと終了タグで囲まれた、h1, p, buttonタグを渡すことができます。
function App() {
const [isModalOpen, setIsModalOpen] = React.useState(true);
return (
<div>
<button onClick={() => setIsModalOpen(true)}>モーダルを開く</button>
<Modal
title="重要なお知らせ"
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
>
<h1>新機能リリースのお知らせ🎉</h1>
<p>新しいダッシュボード機能が追加されました。</p>
<button onClick={() => alert('OK')}>詳細を見る</button>
</Modal>
</div>
);
}childrenの実例2:単一のテキスト
以下のように、単一のテキストをchildrenに渡すこともできます。
function AlertButton({ message, children }) {
return (
<button onClick={() => alert(message)}>
{children}
</button>
);
}
export default function Toolbar() {
return (
<div>
<AlertButton message="Playing!">
再生します
</AlertButton>
<AlertButton message="Uploading!">
アップロードします
</AlertButton>
</div>
);
}childrenを使うことで、全く同じコンポーネントで中身を変えて使いまわすことができます。


