In React, applications are built by assembling small pieces of UI called components. Two closely related concepts that make this approach powerful are component composition and component reusability. Together, they help developers design flexible, scalable, and maintainable applications.
Component composition refers to the practice of combining multiple smaller components to build a larger component or a complete user interface. Instead of creating one large component that handles everything, React encourages breaking the UI into independent, focused components and then composing them together. This approach follows the principle of separation of concerns, where each component has a clear responsibility.
For example, consider a simple page layout. Instead of writing all UI code in one file, you can create separate components for a header, content section, and footer, and then compose them inside a parent component.
Example of component composition:
function Header() {
return <header>Header Section</header>;
}
function Content() {
return <main>Main Content</main>;
}
function Footer() {
return <footer>Footer Section</footer>;
}
function PageLayout() {
return (
<div>
<Header />
<Content />
<Footer />
</div>
);
}
In this example, the PageLayout component is composed of three smaller components. Each component is responsible for a specific part of the UI, making the code easier to understand and maintain.
Component reusability focuses on designing components so they can be used in multiple places with different data or behavior. A reusable component accepts data through props and avoids hardcoding values. This allows the same component to adapt to different scenarios without rewriting code.
Example of a reusable component:
function Button({ label, onClick }) {
return <button onClick={onClick}>{label}</button>;
}
This Button component can be reused across the application with different labels and click behaviors.
Example usage:
<Button label="Save" onClick={handleSave} />
<Button label="Delete" onClick={handleDelete} />
The same component serves multiple purposes, reducing duplication and improving consistency.
A real-world example of component composition and reusability can be seen in form-based applications. A single Input component can be reused for name, email, phone number, and password fields. These inputs can then be composed together to form complex forms such as registration or profile update pages. This approach simplifies changes, as updates to the Input component automatically reflect everywhere it is used.
Component composition also supports advanced patterns such as passing components as children. This allows flexible UI structures where the parent component controls layout and the child components control content.
Example using children:
function Card({ children }) {
return <div className="card">{children}</div>;
}
function Profile() {
return (
<Card>
<h2>User Profile</h2>
<p>Profile details go here</p>
</Card>
);
}
In this case, the Card component is reusable and can wrap different content while maintaining a consistent layout.
Important best practices include keeping components small, avoiding tightly coupled logic, and designing components to be flexible through props. Reusability should be intentional, focusing on common UI patterns rather than forcing reuse in unsuitable scenarios.
In summary, component composition allows developers to build complex interfaces by combining simple components, while component reusability ensures that these components can be used across the application with different data and behavior. Together, these concepts form the foundation of scalable and maintainable React application design.