React Component Composition with Props

In the last lesson you learned about React Children Props, where a component wraps whatever you put between its tags. This lesson goes one step further: combining small components into bigger ones so you build one flexible piece instead of copying it everywhere.

🧩 What Is Component Composition?

Composition just means building bigger components out of smaller ones. Here is the idea broken down.

  • It is the React way of reusing UI. You make small pieces, then snap them together like building blocks.
  • You combine components two ways: by nesting them, and by passing data and other components in through props.
  • A β€œparent” component decides the overall shape. The pieces it gets filled in with come from outside.
  • The goal is one flexible component that works in many situations, instead of many almost-identical copies.

Here is a tiny example. A Page component lays out the structure, and the actual content gets dropped inside it.

function Page() {
return (
<div className="page">
<Header />
<Content />
<Footer />
</div>
);
}

See what happened there?

  • Page is composed of Header, Content, and Footer.
  • None of those pieces know about each other. They just sit together.
  • That is composition in its simplest form.

🎁 Composing With children + props Together

The most common pattern is mixing children with normal props. Here is why that combo is so useful.

  • Use named props for the fixed slots, like a title or a footer. You decide where each one goes.
  • Use children for the main body. Whatever the caller puts between the tags lands there.
  • Together they give you a component with a clear layout but flexible content.

Here is a Card that takes a title prop, a footer prop, and renders children in the middle.

function Card({ title, footer, children }) {
return (
<div className="card">
<h2 className="card-title">{title}</h2>
<div className="card-body">{children}</div>
<div className="card-footer">{footer}</div>
</div>
);
}
function App() {
return (
<Card
title="Welcome back, Alex"
footer={<button>View profile</button>}
>
<p>You have 3 new messages waiting for you.</p>
</Card>
);
}

Walking through it:

  • title is plain text, so it shows up in the heading.
  • footer is actually a whole <button> element passed as a prop. React is happy to take JSX as a prop value.
  • The <p> between the tags becomes children and fills the body.
  • So one Card handles all three slots. The same Card can be a message card today and a settings card tomorrow.

JSX is just a value

You can pass JSX anywhere you pass a normal value: as a prop, in an array, even from a function. That is the whole trick that makes composition work.

πŸ“¦ Passing Components As Props

Sometimes you want a component to take whole sections as props, not just text. Here is how that looks.

  • A layout component can accept a header prop and a sidebar prop, each holding a full component.
  • The layout decides the positions. The caller decides what goes in each position.
  • This keeps the layout reusable. Different pages can drop in different headers and sidebars.

Here is a Page layout that takes header, sidebar, and content as props.

function Page({ header, sidebar, content }) {
return (
<div className="page">
<header className="page-header">{header}</header>
<div className="page-main">
<aside className="page-sidebar">{sidebar}</aside>
<main className="page-content">{content}</main>
</div>
</div>
);
}
function Dashboard() {
return (
<Page
header={<SiteHeader />}
sidebar={<NavMenu />}
content={<ReportList />}
/>
);
}

Notice what Page does and does not know.

  • Page never knows what a header or a sidebar actually contains. It only knows where to place them.
  • Tomorrow you can build a Settings page with the same Page and just swap in different components.
  • So the layout stays. The contents change.

🎯 Specialization: From Generic To Specific

Now a really useful idea called specialization. Here is what it means.

  • Specialization means you build one generic component, then make specific versions of it by passing fixed props.
  • The generic one knows the general shape. The specific one fills in the details once, so callers don’t repeat them.
  • This is how you avoid ten slightly different dialog components. You keep one and specialize it.

Here is a generic Dialog, and a WelcomeDialog that specializes it with fixed content.

function Dialog({ title, message, children }) {
return (
<div className="dialog">
<h1 className="dialog-title">{title}</h1>
<p className="dialog-message">{message}</p>
{children}
</div>
);
}
function WelcomeDialog() {
return (
<Dialog
title="Welcome"
message="Thank you for joining us. We are glad you are here."
>
<button>Get started</button>
</Dialog>
);
}

What is happening:

  • Dialog is the generic piece. It just renders a title, a message, and whatever children you pass.
  • WelcomeDialog is the special version. It hands Dialog a fixed title and message, plus a button as children.
  • Anywhere you want that welcome popup, you just write <WelcomeDialog />. The details live in one place.
  • So if you later want a GoodbyeDialog, you write another small wrapper around the same Dialog. No copy-paste, no duplicated layout.

🚫 Why Composition, Not Inheritance

If you come from another language, you might reach for inheritance to share behavior. In React, you don’t. Here is why.

  • React has no good use case for inheritance between components. The team behind React recommends composition instead.
  • Inheritance ties components together in a rigid chain. Change the base and you risk breaking everything below it.
  • Composition keeps pieces independent. You combine them, but none of them depends on the inner workings of another.
  • Anything you might do with inheritance, you can do more clearly by passing props and children.

Here is the contrast in code. One side tries to extend a base component, the other just composes.

// ❌ Avoid: trying to inherit UI from a base component
class FancyButton extends Button {
// React does not work like this for sharing UI
render() {
return super.render();
}
}
// βœ… Do this: compose by passing props and children
function Button({ style, children }) {
return <button className={style}>{children}</button>;
}
function FancyButton({ children }) {
return <Button style="fancy">{children}</Button>;
}

So FancyButton does not inherit from Button. It just uses Button and passes the right props. That is cleaner and easier to change later.

Coming from class-based languages?

The β€œextend a base class to share UI” habit does not carry over to React. Reach for composition first. Build small components and combine them.

βœ… Best Practices

A few habits that keep composition clean. Here they are.

  • Keep each component focused on one job. Small pieces compose better than big ones.
  • Use children for the main content, and named props for the fixed slots like header or footer.
  • Build generic components first, then specialize them with wrapper components when you need a specific version.
  • Reach for composition before any clever sharing trick. It is the pattern React is built around.

A simple rule

If you feel like copying a component just to change a little bit, stop. Make the original take a prop or children for that part, then compose instead. One flexible component beats five near-copies.

🧩 What You’ve Learned

  • βœ… Composition means building bigger components by combining smaller ones
  • βœ… You can pass whole components as props, like a header or sidebar
  • βœ… children plus named props together give you flexible, well-shaped components
  • βœ… Specialization turns one generic component into specific versions with fixed props
  • βœ… React favors composition over inheritance for sharing and reusing UI

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What does component composition mean in React?

    Why: Composition is about combining small components into bigger ones, by nesting them and by passing data and components through props.

  2. 2

    How can you pass a whole component as a prop?

    Why: JSX is just a value, so you can pass a full element as a prop, for example header={<SiteHeader />}. The parent decides where to place it.

  3. 3

    What is specialization in React?

    Why: Specialization means a generic component (like Dialog) becomes a specific one (like WelcomeDialog) by passing fixed props and children.

  4. 4

    Why does React favor composition over inheritance?

    Why: Composition keeps components independent and flexible. React has no good use case for inheritance between components, so composition is the recommended pattern.

πŸš€ What’s Next?

Now you can combine components into flexible UIs instead of copying layouts everywhere. Next, let’s tidy up how you actually pass data into them with some solid habits.

React Props Best Practices

Share & Connect