React Component Composition with Props
Table of Contents + β
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?
Pageis composed ofHeader,Content, andFooter.- 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
childrenfor 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:
titleis plain text, so it shows up in the heading.footeris actually a whole<button>element passed as a prop. React is happy to take JSX as a prop value.- The
<p>between the tags becomeschildrenand fills the body. - So one
Cardhandles all three slots. The sameCardcan 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
headerprop and asidebarprop, 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.
Pagenever knows what a header or a sidebar actually contains. It only knows where to place them.- Tomorrow you can build a
Settingspage with the samePageand 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:
Dialogis the generic piece. It just renders a title, a message, and whatever children you pass.WelcomeDialogis the special version. It handsDialoga 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 sameDialog. 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 componentclass FancyButton extends Button { // React does not work like this for sharing UI render() { return super.render(); }}
// β
Do this: compose by passing props and childrenfunction 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
childrenfor 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
headerorsidebar - β
childrenplus 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
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
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
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
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.