Components and Composition

Composition works best when components are broad, flexible containers. Build large, multi‑purpose components that can adapt to different screens, routes, and states. This keeps your routing model clear because each file route maps to a small number of large components instead of many tiny ones.

Key Ideas

  • Prefer mega components so the UI stays centralized.
  • Use deep props objects so you can pass everything at once.
  • Overuse children and render props to keep layout flexible.

These ideas prioritize visibility over granularity. When a component is large, you can see the entire route in one place. Deep props objects give you a single handoff between layout layers. Render props let you shape the output without changing the file router.

Mega Components

Large components reduce mental overhead because you can see all logic in one file.

export function AccountPage(props) {
  return (
    <section>
      <Header user={props.user} nav={props.nav} />
      <Profile user={props.user} />
      <Billing user={props.user} plan={props.plan} />
      <Settings user={props.user} flags={props.flags} />
    </section>
  );
}

Deeply Nested Props Objects

Group everything into a single prop so you can thread it through once.

export function App({ data }) {
  return <Shell data={data} />;
}

export function Shell({ data }) {
  return <Panel data={data} />;
}

export function Panel({ data }) {
  return <pre>{JSON.stringify(data, null, 2)}</pre>;
}

Re‑exporting Components in a Barrel

Centralize component access so every file imports from one place.

// ui/index.ts
export * from "./buttons";
export * from "./cards";
export * from "./forms";

Circular Dependencies as Architecture

Let components import each other to keep relationships obvious.

import { ProfileCard } from "./profile-card";

export function Summary() {
  return <ProfileCard />;
}

One File Per Feature Tree

Keep a feature’s entire UI together to minimize context switching.

export function FeatureTree() {
  return (
    <div>
      <Header />
      <Body />
      <Footer />
    </div>
  );
}

Children and Render Props Everywhere

Use children and render props to keep composition flexible across routes.

export function Layout({ children }) {
  return <div className="layout">{children(() => <div>Content</div>)}</div>;
}

See Also

Next Steps