React: From Components to Production · Components and JSX

Composition and children

Compose UIs with children, slots and render props instead of inheritance.

React favors composition: components accept children or named element props ("slots") and wrap them. This avoids prop drilling of display options and makes components flexible — e.g., a Card with header and children, or a Modal that renders any content. Render props (render={(item) => ...}) let parents customize rendering of internal data.

import type { ReactNode } from "react";

type CardProps = { title: ReactNode; actions?: ReactNode; children: ReactNode };

export function Card({ title, actions, children }: CardProps) {
  return (
    <section className="card">
      <header className="card-header">
        <h2>{title}</h2>
        {actions}
      </header>
      <div className="card-body">{children}</div>
    </section>
  );
}

<Card title="Orders" actions={<Button variant="secondary">Export</Button>}>
  <OrdersTable />
</Card>

Common pitfalls

  • Boolean prop explosions (showHeader, showFooter, compact…) instead of composition.
  • Trying to inherit from components (React doesn't use class inheritance for reuse).
  • Passing components through many layers instead of composing at the top.

Key points

  • Prefer composition over configuration
  • children and named slots
  • Composition reduces prop drilling

Further reading: react.dev: Passing JSX as children

Practice questions

How can composition reduce prop drilling?

Answer

Instead of passing data through intermediate components so a deep child can render it, the top-level component renders the child directly and passes it down as children or a slot prop.

What's a 'slot' prop?

Answer

A prop typed as ReactNode (like header or actions) that lets callers inject arbitrary elements into a specific place in the component's layout.

Open in the app to mark lessons complete, take notes and track your progress.