miscellaneous
Component Composition and Reusability — Building a Flexible UI System
Learn component composition in React—design scalable, reusable, and flexible UIs using children, props, higher-order components, custom hooks, and industry best practices.
Article 3: Component Composition and Reusability — Building a Flexible UI System
Learning Objectives
By the end of this article, you will:
- Understand what component composition means in React and why it’s the backbone of scalable, maintainable apps.
- Discover patterns for composing components—from children and props to advanced techniques like higher-order components and custom hooks.
- Learn to design reusable, flexible components following modern industry practices.
- Recognize the distinction between “presentational” and “container” components, and know when and how to use each.
- Practice with hands-on exercises and project ideas that turn theory into practical UI craftsmanship.
Why Component Composition? The Power of Lego-Like UIs
Imagine you’re constructing a sprawling apartment complex. You wouldn’t reinvent each floor, pillar, or balcony; instead, you’d use standardized designs that fit together perfectly. That’s exactly how React’s component composition works. By composing simple components into more complex ones, you avoid code duplication, boost maintainability, and give your UI team superpowers for rapid iteration.
In India’s tech scene, where teams need to deliver quality and features fast, composition and reusability are keys to scaling projects efficiently—whether it’s building fintech dashboards or educational platforms.
The Basics: Composition over Inheritance
React encourages composition, not inheritance. That means you combine smaller, focused components together, rather than extending big “base” components.
Example: Building with Composition
// Button.js
export function Button({ children, onClick }) {
return <button onClick={onClick}>{children}</button>;
}
// Dialog.js
export function Dialog({ title, children }) {
return (
<div className="dialog">
<h3>{title}</h3>
{children}
</div>
);
}
// Usage
<Dialog title="Login Required">
<Button onClick={handleLogin}>Log In</Button>
</Dialog>;
See how the Dialog
accepts children?
This is the most basic, yet powerful, tool for composing components in React.
Component Reusability: Write Once, Use Everywhere
Reusable components make your development lightning fast.
What makes a component reusable?
- Accepts dynamic data via props.
- Avoids hard-coding styles, text, or behavior.
- Has a clear, focused purpose (“does one thing well”).
Example: A Reusable Card
export function Card({ title, content, footer }) {
return (
<div className="card">
<h4>{title}</h4>
<div>{content}</div>
<div>{footer}</div>
</div>
);
}
// Usage
<Card
title="React Jobs in Noida"
content="10 new opportunities."
footer={<Button>Apply Now</Button>}
/>;
The Special Power of children
Prop
The children
prop is a built-in way to let you pass JSX into any component.
Why use children
?
- Decouples layout/structure from content.
- Lets you nest components flexibly.
function FancyBorder({ children }) {
return <div className="fancy-border">{children}</div>;
}
<FancyBorder>
<p>This is inside a border!</p>
</FancyBorder>;
Advanced Composition Patterns
1. Render Props
A technique for sharing code between components using a function as a prop.
Pattern:
function DataFetcher({ url, children }) {
const [data, setData] = useState(null);
// fetch data (omitted)
return children(data);
}
// Usage
<DataFetcher url="/api/jobs">
{(data) => (data ? <JobList jobs={data} /> : <Spinner />)}
</DataFetcher>;
2. Higher-Order Components (HoCs)
A function that takes a component and returns a new component. Used for cross-cutting concerns like authentication or logging.
Pattern:
function withLoading(Component) {
return function WrappedComponent({ isLoading, ...props }) {
if (isLoading) return <Spinner />;
return <Component {...props} />;
};
}
// Usage: const JobsWithLoading = withLoading(JobsList);
Note: Modern React favors hooks over many HoC use-cases, but you’ll spot HoCs in many real projects.
3. Custom Hooks
Encapsulate reusable logic outside the UI tree.
function useCounter(initial = 0) {
const [count, setCount] = useState(initial);
const increment = () => setCount((c) => c + 1);
return [count, increment];
}
Presentational vs. Container Components (Smart & Dumb)
- Presentational (Dumb) Components:
- Only display data via props; no business logic.
- Examples:
Button
,Avatar
,ProfileCard
.
- Container (Smart) Components:
- Handle data fetching, state, and logic.
- Pass data to presentational components as props.
Why? This separation keeps your UI clean and maintainable—designers can work on look-and-feel, while developers focus on logic.
Industry Best Practices & Tips
- Small, focused components are easier to test, reuse, and maintain.
- Always prefer composition to inheritance.
- Use the
children
prop for flexible layouts and slots. - Make UI components stateless when possible; delegate data and logic.
- Use custom hooks for sharing logic instead of HoCs unless needed for legacy or third-party code.
- Document your reusable components—they’ll be part of your team’s “toolbox.”
Anti-patterns to Avoid
- Monolithic components: Trying to do too much—break them up!
- Hardcoding values: Don’t tie your component to one use-case.
- Uncontrolled use of Context/Redux: Keep data as local as possible.
Practice Exercises
- Reusable Button: Create a Button component that accepts children, a type (
primary
,secondary
), and an onClick handler. Use it for various roles—Submit, Cancel, Delete. - Composed Layout: Create a
PageLayout
component that renders a sidebar, header, and main content using children and props. - Render Prop Challenge: Build a Tooltip component that shows info when hovered, using a render prop for its trigger.
Project Idea
Professional Feature: Build a Dashboard layout with Sidebar, Topbar, and Content area. Each area is a composable component.
- Use props and children for maximum flexibility.
- Add widgets (Weather, News, Notifications) as reusable components to the content area.
Further Reading & Resources
- Component Composition in React
- Reusable components best practices — FreeCodeCamp
- Hooks FAQ and Patterns
Final Thoughts: From Bricks to Buildings
Every great React interface is just a clever arrangement of simple, reusable components. If you embrace composition and strive for DRY (Don’t Repeat Yourself) code, your projects will scale beautifully and your teammates will thank you.
Next up: Let’s dive into performance optimization, where you’ll learn how to keep your apps snappy and your users delighted—no matter how many re-usable Lego blocks you’ve stacked together!