Skip to main content
Practice Problems

Composition vs inheritance in React

Composition vs Inheritance

React strongly favors composition over inheritance. Instead of extending components through class hierarchies, you compose them by combining smaller components together.


Composition with children

tsx
// A generic container component function Card({ children, title }: { children: React.ReactNode; title: string }) { return ( <div className="card"> <h2>{title}</h2> <div className="card-body">{children}</div> </div> ); } // Compose different cards function App() { return ( <> <Card title="Profile"> <Avatar /> <UserInfo /> </Card> <Card title="Settings"> <SettingsForm /> </Card> </> ); }

Specialization Pattern

Create specialized versions of a generic component:

tsx
// Generic Dialog function Dialog({ title, message, children }: { title: string; message: string; children?: React.ReactNode; }) { return ( <div className="dialog"> <h1>{title}</h1> <p>{message}</p> {children} </div> ); } // Specialized dialogs via composition function WelcomeDialog() { return ( <Dialog title="Welcome!" message="Thanks for joining our platform." /> ); } function DeleteConfirmDialog({ onConfirm }: { onConfirm: () => void }) { return ( <Dialog title="Delete?" message="This action cannot be undone."> <button onClick={onConfirm}>Yes, delete</button> </Dialog> ); }

Slot Pattern (Named Composition)

tsx
function Layout({ header, sidebar, content, footer }: { header: React.ReactNode; sidebar: React.ReactNode; content: React.ReactNode; footer: React.ReactNode; }) { return ( <div className="layout"> <header>{header}</header> <aside>{sidebar}</aside> <main>{content}</main> <footer>{footer}</footer> </div> ); } // Use named slots <Layout header={<Navbar />} sidebar={<Sidebar />} content={<MainContent />} footer={<Footer />} />

Why NOT Inheritance?

tsx
// ❌ Inheritance — DON'T do this in React class Button extends React.Component { /* ... */ } class PrimaryButton extends Button { /* ... */ } class DangerButton extends PrimaryButton { /* ... */ } // Rigid hierarchy, hard to change // ✅ Composition — DO this instead function Button({ variant, children, ...props }: ButtonProps) { return <button className={`btn btn-${variant}`} {...props}>{children}</button>; } <Button variant="primary">Save</Button> <Button variant="danger">Delete</Button>

Composition Patterns Summary

PatternHowUse Case
childrenPass JSX as childrenGeneric containers, wrappers
SpecializationPre-fill props of generic componentSpecific dialog, button variants
SlotsNamed props for different areasLayouts, complex UI
Render PropsPass function as propDynamic rendering logic
HOCWrap component with anotherCross-cutting concerns

Important:

React team recommends composition over inheritance in all cases. Use children, named props (slots), and component composition to build flexible UIs. Inheritance creates rigid hierarchies that are hard to refactor — composition keeps components independent and reusable.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems