# Children in React: Complete Guide to Composition and the React.Children API

> Master React children and composition with our complete guide. Learn to use props.children for dynamic content and reusable UI elements effectively.

- Repository: [Meta/react](https://github.com/facebook/react)
- Tags: deep-dive
- Published: 2026-02-16

---

**Children in React are elements passed between a component's opening and closing JSX tags, accessible via `props.children`, and should be used for component composition and dynamic content wrapping.**

In the `facebook/react` repository, children represent an **opaque data structure** that can contain a single React element, an array of elements, strings, numbers, fragments, or `null` values. Understanding how to work with children in React enables you to build flexible, reusable wrapper components without hardcoding their contents.

## What Are Children in React?

When you nest content inside a JSX tag, React passes that content to the component function as a special property called `props.children`:

```jsx
<Card>
  <h1>Title</h1>
  <p>Content here</p>
</Card>

```

Inside `Card`, the nested `<h1>` and `<p>` elements arrive as `props.children`. According to the React source code in [`packages/react/src/ReactChildren.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactChildren.js), React treats this property as an opaque data structure that requires specialized utilities to traverse safely. Directly manipulating `props.children` with array methods can fail when children contain fragments, lazy components, or nested arrays.

## When to Use Children in React

Use children in React when building **composable wrapper components** that need to render arbitrary content without knowing its structure ahead of time. This pattern appears in layout components, modal dialogs, context providers, and styling containers.

The primary use cases include:

- **Component composition** – Creating reusable containers like cards, modals, or page layouts that accept any valid React element as content.
- **Dynamic content injection** – Wrapping children with additional styling, event handlers, or context providers before rendering.
- **List processing** – Transforming or validating collections of elements using the `React.Children` API.
- **Layout control** – Flattening nested structures or enforcing single-child constraints for specialized components.

## The React.Children API for Safe Manipulation

The `React.Children` API provides five utility functions implemented in [`packages/react/src/ReactChildren.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactChildren.js) to traverse and manipulate the opaque children data structure safely. These utilities handle edge cases like `null` values, fragments, and lazy components automatically.

### Mapping and Transforming with React.Children.map

Use `React.Children.map` to iterate over children and return a new array of transformed elements. Unlike `Array.prototype.map`, this utility handles nested arrays and fragments correctly:

```jsx
import React from 'react';

export default function List({ children }) {
  const items = React.Children.map(children, child =>
    React.isValidElement(child)
      ? React.cloneElement(child, {
          className: `${child.props.className ?? ''} list-item`,
        })
      : child
  );

  return <ul>{items}</ul>;
}

```

This pattern relies on `isValidElement` and `cloneAndReplaceKey` from [`packages/react/src/jsx/ReactJSXElement.js`](https://github.com/facebook/react/blob/main/packages/react/src/jsx/ReactJSXElement.js) to safely augment each child.

### Iteration with React.Children.forEach

`React.Children.forEach` executes a function for each child without returning a new array. Use this for side effects like logging or validation:

```jsx
React.Children.forEach(children, (child, index) => {
  console.log(`Child ${index}:`, child);
});

```

### Counting with React.Children.count

`React.Children.count` returns the total number of leaf nodes in the children structure, including nested arrays and fragments:

```jsx
import React from 'react';

export default function MaxTwo({ children }) {
  const count = React.Children.count(children);
  if (count > 2) {
    console.warn('MaxTwo expects at most 2 children');
  }
  return <div>{children}</div>;
}

```

### Enforcing Single Child with React.Children.only

`React.Children.only` validates that children contains exactly one React element, throwing an error otherwise. Use this for components that require a single content node:

```jsx
import React from 'react';

export default function Modal({ children }) {
  const content = React.Children.only(children);
  
  return (
    <div className="modal">
      <div className="modal-content">{content}</div>
    </div>
  );
}

```

### Flattening with React.Children.toArray

`React.Children.toArray` converts any children structure into a flat array with assigned keys, handling fragments and nested arrays automatically:

```jsx
import React from 'react';

export default function Grid({ children }) {
  const flat = React.Children.toArray(children);
  
  return (
    <div className="grid">
      {flat.map((child, i) => (
        <div key={i} className="grid-cell">
          {child}
        </div>
      ))}
    </div>
  );
}

```

## Core Implementation Files in the React Source

The children functionality in React is implemented across these key files in the `facebook/react` repository:

- **[`packages/react/src/ReactChildren.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactChildren.js)** – Contains the core implementations of `React.Children.map`, `forEach`, `count`, `only`, and `toArray`, handling the opaque traversal logic.
- **[`packages/react/src/jsx/ReactJSXElement.js`](https://github.com/facebook/react/blob/main/packages/react/src/jsx/ReactJSXElement.js)** – Defines `isValidElement` and `cloneAndReplaceKey`, which the children utilities rely on for element validation and cloning.
- **[`packages/react/src/__tests__/ReactChildren-test.js`](https://github.com/facebook/react/blob/main/packages/react/src/__tests__/ReactChildren-test.js)** – Comprehensive test suite documenting expected behaviors for fragments, lazy components, and edge cases like `null` or `boolean` children.

## Summary

- **Children in React** are elements passed between JSX tags, accessible via `props.children` as an opaque data structure.
- Use children for **component composition**, creating flexible wrapper components like cards, modals, and layouts.
- Always use the **`React.Children` API** (`map`, `forEach`, `count`, `only`, `toArray`) instead of manual array methods to handle fragments, lazy components, and nested arrays safely.
- The implementation resides in [`packages/react/src/ReactChildren.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactChildren.js) and relies on element utilities from [`packages/react/src/jsx/ReactJSXElement.js`](https://github.com/facebook/react/blob/main/packages/react/src/jsx/ReactJSXElement.js).

## Frequently Asked Questions

### What is the difference between using `props.children` directly versus `React.Children.toArray`?

Using `props.children` directly preserves the original opaque structure, which might be a single element, nested array, or fragment. **`React.Children.toArray`** flattens nested structures into a single array with stable keys, making it safer for iteration or indexing operations when you need predictable array behavior.

### When should I use `React.Children.map` instead of `Array.prototype.map`?

Use **`React.Children.map`** whenever you need to transform children that might contain fragments, nested arrays, or lazy components. Unlike `Array.prototype.map`, the React utility handles the opaque children structure correctly, resolving lazy components and flattening fragments automatically as implemented in [`packages/react/src/ReactChildren.js`](https://github.com/facebook/react/blob/main/packages/react/src/ReactChildren.js).

### Why does `React.Children.only` throw an error when I pass multiple elements?

**`React.Children.only`** is designed for components that architecturally require exactly one child element, such as a modal content container or animation wrapper. If you pass zero or multiple elements, it throws immediately to enforce this constraint at development time, preventing runtime layout errors.

### Can I use children with TypeScript, and how do I type them correctly?

Yes, children in React work seamlessly with TypeScript. Use the **`ReactNode`** type from the `react` package to accept any valid child (elements, strings, numbers, fragments, arrays, or null). For single-child constraints, use **`ReactElement`** or **`ReactElement | null`** to match the behavior of `React.Children.only`.