Md Arshad Khan | Full Stack Engineer Logo
React,  frontend

React Composition: The Pattern That Changed How I Build Components

Author

Md Arshad Khan

Date Published

blog-hero-image

What Is Composition?

Most developers overthink component reusability. They create massive prop APIs, nested ternaries, and components with 20+ props that nobody wants to maintain.

Here’s what I learned after refactoring hundreds of components: composition beats configuration every single time.

The Problem With Prop Drilling

Composition is React’s way of building complex UIs by combining smaller, focused components . Instead of cramming logic into one giant component, you nest components inside each other like building blocks .

Think of it like LEGO. You don’t need one massive piece. You combine small pieces to create anything.

The Composition Solution

Here’s the old way most developers (including past me) built a Card component:

1function Card({ title, content, showFooter, footerText, hasIcon, iconPosition }) {
2 return (
3 <div className="card">
4 {hasIcon && iconPosition === 'left' && <Icon />}
5 <h2>{title}</h2>
6 <p>{content}</p>
7 {hasIcon && iconPosition === 'right' && <Icon />}
8 {showFooter && <footer>{footerText}</footer>}
9 </div>
10 );
11}
12

This gets messy fast. Every new variant needs a new prop

The Composition Solution

Here’s the same component using composition:

1function Card({ children }) {
2 return <div className="card">{children}</div>;
3}
4
5function CardHeader({ children }) {
6 return <div className="card-header">{children}</div>;
7}
8
9function CardBody({ children }) {
10 return <div className="card-body">{children}</div>;
11}
12
13function CardFooter({ children }) {
14 return <div className="card-footer">{children}</div>;
15}
16

Now you compose them however you need:

1function UserProfile() {
2 return (
3 <Card>
4 <CardHeader>
5 <Icon position="left" />
6 <h2>John Doe</h2>
7 </CardHeader>
8 <CardBody>
9 <p>Frontend Engineer specializing in React performance</p>
10 </CardBody>
11 <CardFooter>
12 <button>View Profile</button>
13 </CardFooter>
14 </Card>
15 );
16}
17


1function SimpleCard() {
2 return (
3 <Card>
4 <CardBody>
5 <p>Just a simple card. No header needed.</p>
6 </CardBody>
7 </Card>
8 );
9}
10

Same components, infinite flexibility

Why This Matters in Real Projects

When I migrated a financial analytics dashboard, we had 47 different card variants. The old prop-based approach was unmaintainable .

After switching to composition:

Added new variants in minutes, not hours

Reduced bundle size by 18% (removed unused prop logic)

Onboarded new developers faster (self-documenting structure)

Testing became simpler (test small pieces, not giant components)

Composition With Hooks

You can supercharge composition with custom hooks

1function useCardAnimation() {
2 const [isVisible, setIsVisible] = useState(false);
3
4 useEffect(() => {
5 setIsVisible(true);
6 }, []);
7
8 return isVisible;
9}
10
11function AnimatedCard({ children }) {
12 const isVisible = useCardAnimation();
13
14 return (
15 <div className={isVisible ? 'card-enter' : 'card'}>
16 {children}
17 </div>
18 );
19}
20

Logic lives in hooks. UI lives in components. Clean separation

When to Use Composition

Use composition when you need :

Reusable UI elements with variations

Complex layouts that share structure

Component libraries

Clear parent-child relationships

The React Team’s Recommendation

React’s official docs are clear: use composition over inheritance . Inheritance creates tight coupling and reduces flexibility. Composition keeps components small, focused, and easy to test .

Your Turn

What’s one component in your codebase that could benefit from composition? Try refactoring it this weekend. You’ll be surprised how much cleaner it feels.