Reactの children を理解する



## 1. `children` とは何か？

`children` は、React コンポーネントに渡される特別な props のひとつです。
コンポーネントの **開始タグと終了タグのあいだに書かれた内容**が、自動的に `props.children` として渡されます。

```tsx
function Box({ children }) {
  return <div>{children}</div>;
}

<Box>
  <p>Hello</p>
</Box>
```

このとき、Reactは以下のように props を解釈します：

```js
{
  children: <p>Hello</p>
}
```

つまり、React のコンポーネントを「箱」と見立てると、`children` はその中に**詰められた中身**です。

* 親コンポーネントは「枠」や「構造」を定義
* `children` はその中に自由に詰め込める「内容」

この仕組みによって、コンポーネントの中身を外部から差し替えたり、再利用したりすることが可能になります。

## 2.`children` の使い方パターン

### パターン①：そのまま描画する（汎用ラッパー）


もっとも基本的な使い方。`children` を単純にそのまま描画する。

```tsx
function Container({ children }) {
  return <div className="container">{children}</div>;
}
```

```tsx
<Container>
  <p>Hello</p>
</Container>
```

#### 向いている場面

* カード、ボックス、レイアウト、モーダルなどの汎用 UI
* コンテンツに制限を持たせず自由に使いたいとき

### パターン②：`children` に処理を加える（map や wrap）

`children` に共通の加工（ラップ、装飾など）を施す。
複数の子を処理する際には `React.Children.map` を使用。

```tsx
function List({ children }) {
  return (
    <ul>
      {React.Children.map(children, child => (
        <li>{child}</li>
      ))}
    </ul>
  );
}
```

```tsx
<List>
  <span>Apple</span>
  <span>Banana</span>
</List>
```

#### 向いている場面

* リストアイテム、ナビゲーション、複数要素の装飾
* コンテンツの個別レンダリングが必要な場面

### パターン③：Function as Children（関数として子を渡す）

`children` を関数として渡し、親が状態を与えてレンダリングを制御。

```tsx
function MouseTracker({ children }) {
  const [pos, setPos] = useState({ x: 0, y: 0 });
  useEffect(() => {
    const move = e => setPos({ x: e.clientX, y: e.clientY });
    window.addEventListener("mousemove", move);
    return () => window.removeEventListener("mousemove", move);
  }, []);
  return children(pos);
}
```

```tsx
<MouseTracker>
  {pos => <p>Mouse at {pos.x}, {pos.y}</p>}
</MouseTracker>
```

#### 向いている場面

* 状態に応じたカスタム描画（例：グラフ、レスポンシブ対応）
* ロジックとUIを分離したいケース

### パターン④：Compound Component（構造的スロット）


子要素を名前付きコンポーネント（スロット）として構造的に分けるパターン。

```tsx
function Card({ children }) {
  const header = React.Children.toArray(children).find(
    c => c.type === Card.Header
  );
  const body = React.Children.toArray(children).find(
    c => c.type === Card.Body
  );

  return (
    <div>
      <div className="card-header">{header}</div>
      <div className="card-body">{body}</div>
    </div>
  );
}

Card.Header = ({ children }) => <>{children}</>;
Card.Body = ({ children }) => <>{children}</>;
```

```tsx
<Card>
  <Card.Header>タイトル</Card.Header>
  <Card.Body>本文</Card.Body>
</Card>
```
#### 向いている場面

* タブ、フォーム、モーダル、カードなどの複合 UI
* 設計の明確さ・保守性を求めるケース



## 3. `children` の注意点と落とし穴

React公式ドキュメントでは次のように述べられています：

> **「`children` の使用は一般的ではなく、コードが壊れやすくなる可能性があります」**
> “It’s uncommon to use `children` directly because it makes your code fragile.”
> – [React.dev - Passing Props](https://react.dev/learn/passing-props-to-a-component#children-props)

これは「`children` 自体を使うな」という意味ではなく、
**`children` の構造や順番に依存する設計をすると、脆くなるので注意せよ**という警告です。


###  落とし穴①：**順番に依存した実装**

```tsx
function Layout({ children }) {
  const header = children[0]; // 1番目を header と決め打ち
  const content = children[1];
  return (
    <>
      <header>{header}</header>
      <main>{content}</main>
    </>
  );
}
```

#### なぜ危険？

* 子要素が1つだけだと `children` は配列ではなくなる（構文エラーの原因）
* 呼び出し側が順番を間違えると崩れる
* 他の開発者が使う際に仕様がわかりにくい


### 落とし穴②：**構造を前提にして `children` をハードコード**

```tsx
function Item({ children }) {
  return <li>{children}</li>;
}

<Item>
  <span>Apple</span>
  <span>Banana</span>
</Item>
```

#### なぜ危険？

* `<li>` の中に複数の要素が入ると HTML 構造的に不正になる可能性がある
* ブラウザによっては正しく解釈されず意図しない表示になる


### 落とし穴③：**`children` の中身に型を仮定する**

```tsx
if (typeof children === 'string') {
  // 文字列として処理
}
```

#### なぜ危険？

* `children` は JSX、配列、関数、null など様々な型を取りうる
* このような分岐は意図しない挙動や壊れやすい設計につながる



##  4. 安全に扱うためには

### ① `React.Children.map()` を使う

```tsx
<ul>
  {React.Children.map(children, child => (
    <li>{child}</li>
  ))}
</ul>
```

* 子要素が単一でも複数でも一貫して処理可能
* `key` を指定することも可能
* 配列かどうかを気にせず扱える

### ② `React.Children.toArray()` を使って明示的に配列化

```tsx
const childArray = React.Children.toArray(children);
childArray.map(child => <div>{child}</div>);
```

* 配列としてループ処理でき、React が自動で `key` をつけてくれる
* 順序操作・フィルタリングなどがしやすくなる

###  ③ 明示的な props を使う（構造に依存しない設計）

```tsx
function Layout({ header, content }) {
  return (
    <>
      <header>{header}</header>
      <main>{content}</main>
    </>
  );
}
```

```tsx
<Layout
  header={<Header />}
  content={<Main />}
/>
```

* `children[0]` のように構造に依存しない
* 呼び出し側の意図も明確で安全


### ④ Compound Component パターンで構造を明示化

```tsx
<Modal>
  <Modal.Title>タイトル</Modal.Title>
  <Modal.Content>本文</Modal.Content>
</Modal>
```

```tsx
function Modal({ children }) {
  const title = React.Children.toArray(children).find(child => child.type === Modal.Title);
  const content = React.Children.toArray(children).find(child => child.type === Modal.Content);
  return (
    <>
      <h1>{title}</h1>
      <div>{content}</div>
    </>
  );
}
Modal.Title = ({ children }) => <>{children}</>;
Modal.Content = ({ children }) => <>{children}</>;
```

* JSX構文を保ちながら、**意味による構造分離**ができる
* 柔軟かつ堅牢な設計パターン


### ⑤ TypeScript で型の曖昧さを制御

```ts
type Props = {
  children: React.ReactNode;
};
```

または制約を加えるなら：

```ts
type Props = {
  children: React.ReactElement<MyComponentProps>[];
};
```

* `children` の許容値を型で明示
* 特定の要素のみ受け入れるように制限も可能

## まとめ

* **`children` は React コンポーネントのタグの中に書かれた中身**
* 技術的には `props.children` として自動的に渡される「特別な props」
* 概念的には、**「中身を外部から差し込む柔軟な仕組み」**
* 子要素の **順番や数に依存する設計**（例: `children[0]`）は壊れやすい
* `<li>{children}</li>` のように **HTML構造に不適な使い方**をしない
* `children` の型を **仮定しない**（stringとは限らない）