children

Receive whatever JSX is nested inside a component's tags and render it wherever you want.

Signature
<Component>{children}</Component>  // children?: ReactNode

Parameters

ParameterTypeDescription
$childrenoptionalReactNode= undefinedA React node: an element, a string, a number, a portal, null, undefined, a boolean, or an array of React nodes. Anything nested between the component's opening and closing tags arrives here.

Errors

Passing both children and dangerouslySetInnerHTML to the same element throws.

children is an ordinary prop with a syntax shortcut: whatever you nest between a component's tags is collected into it. That is what lets a component be a shape with a hole in it — a card, a modal, a page layout — that the caller fills with arbitrary JSX.

When to reach for it

  • Visual wrappers: panels, cards, grids, dialogs, error boundaries.
  • Anywhere passing markup is simpler than passing a dozen configuration props.

What trips people up

It is not always an array. One nested element gives you that element; several give you an array; none gives you undefined. Do not index into it — render it with {children} and let React handle the shape.

null, undefined, true and false all render as nothing, which is why {condition && } is safe as a child. A 0 is not: it renders the digit.

When you need more than one hole, do not try to slice children apart. Give the component several props that each hold JSX (header, footer) — they are just as valid, and far easier to read than Children.toArray.

Children written between the tags win over an explicit children={...} attribute on the same element.

Example

Try it yourself
Loading editor…
Loading React…

When to use it

  • A Card or Panel component that frames any content passed to it
  • A page Layout that renders a header, the nested page, and a footer
  • A permission gate that renders its children only when the user is allowed
  • A list component that lets the caller decide how each row is rendered

Frequently asked questions

How do I type children in TypeScript?

Declare it as React.ReactNode: function Card({ children }: { children?: React.ReactNode }). ReactNode covers elements, strings, numbers, arrays, null and booleans. Avoid JSX.Element, which rejects strings and multiple children.

How do I count or iterate over children?

Use React.Children.count and React.Children.map, never children.length or a plain .map — a single child is not wrapped in an array. In most cases the better fix is to accept an array prop or separate slot props instead.

Why does my component render nothing when I nest content in it?

Because the component never renders {children}. Accepting the prop is not enough; the JSX you nest is only displayed at the point where the component outputs it.

More examples

Several holes: JSX passed as ordinary props

Three separate slots without touching the Children API. header and footer are props holding JSX, the nested paragraph arrives as children. This is the pattern to reach for instead of inspecting children to work out which piece is which — each slot is named, optional, and type-checkable.

Example · jsx
function Dialog({ header, footer, children }) {
  return (
    <div className="dialog">
      <div className="dialog-header">{header}</div>
      <div className="dialog-body">{children}</div>
      <div className="dialog-footer">{footer}</div>
    </div>
  );
}

export default function ConfirmDelete() {
  return (
    <Dialog
      header={<h3>Delete project?</h3>}
      footer={
        <>
          <button>Cancel</button>
          <button>Delete</button>
        </>
      }
    >
      <p>This removes every build and cannot be undone.</p>
    </Dialog>
  );
}

children as a function (render prop)

Here children is a function rather than a node, so the parent can hand state down to whatever the caller renders. React never renders a function directly: returning children unchanged renders nothing and logs "Functions are not valid as a React child" in development, so Toggle has to call it. Hooks cover most of what render props were used for, but the pattern still fits components that own DOM measurement or subscription logic.

Example · jsx
import { useState } from "react";

function Toggle({ children }) {
  const [on, setOn] = useState(false);
  return children({ on, toggle: () => setOn((v) => !v) });
}

export default function Settings() {
  return (
    <Toggle>
      {({ on, toggle }) => (
        <p>
          Notifications are {on ? "on" : "off"}{" "}
          <button onClick={toggle}>Toggle</button>
        </p>
      )}
    </Toggle>
  );
}

Discussion

  • Be the first to comment on this lesson.