Understanding Component Composition in React
Frontend Developer, Community Manager volunteer at Edustipend, DSA community manager at Nexascale, BeerJs Lokoja community lead, Co-lead GDG Lokoja.
In React, component composition is a core concept for building flexible and reusable components. It involves organizing components by including or “composing” them within one another. When used effectively, this principle allows for a modular, flexible structure where components can dynamically interact and adapt to different situations.
The Problem of Hard-Coded Components in JSX
Consider an example where we have a Modal component that displays a Success message to users. One way to achieve this is by simply including the Success component within the Modal component.
// Success.js
const Success = () => <p>Well done!</p>;
// Modal.js
const Modal = () => (
<div className="modal">
<Success /> {/* Displays the success message */}
</div>
);

In this example, the Success component is embedded directly within Modal. While this setup works, it also tightly couples the Modal to the Success component, making it difficult to reuse Modal for other messages, such as errors or warnings. To enhance usability, we need a more flexible solution.
Introducing Component Composition with the children Prop
Component composition allows us to "decouple" components, making them adaptable and reusable to different use cases. By taking advantage of the children prop, we can make Modal more flexible and allow it to display any content passed to it. Here’s how.
// Modal.js
const Modal = ({ children }) => (
<div className="modal">
{children} {/* Content is now dynamic */}
</div>
);
Now, Modal does not contain any hard-coded components but instead renders whatever is passed between its opening and closing tags, like so
// Usage of Modal.js
<Modal>
<Success /> {/* Display success message */}
</Modal>
<Modal>
<Error /> {/* Display error message */}
</Modal>

In the example above, Modal can render both Success and Error components because they are passed as children. This simple change unlocks the potential to use Modal in various contexts across the application.
By using the children prop, we’ve created a "slot" within Modal that can be filled with any content, making it highly reusable for different message types or layouts.
Formal Definition of Component Composition
In React, component composition is formally defined as combining components in one of two ways:
Using the
childrenProp: This is a common approach where we nest components and allow flexible content inside the parent.Passing Components as Props: Besides
children, we can pass components explicitly as props to enable advanced composition.
// Passing components as props
const Modal = ({ Header, Content }) => (
<div className="modal">
<Header />
<Content />
</div>
);
// Using the Modal
<Modal
Header={() => <h2>Alert</h2>}
Content={() => <p>This is an alert message.</p>}
/>

Why Use Component Composition?
There are two main scenarios where component composition shines:
Creating Reusable, Flexible Components: By designing components like
Modalto be flexible, we can use them in multiple contexts without rewriting code.Solving Prop Drilling Problems: Composition also allows data or components to be passed through the app structure without complicated prop drilling. This is especially useful when building layouts where multiple components may need access to shared elements or
state.
Conclusion
Component composition allows us to leave empty "slots" in components, creating reusable structures that can fit into different contexts. By utilizing the children prop and component-based props, we decouple our components, making them flexible and modular. This powerful principle is foundational in React, promoting clean, maintainable code while empowering us to build scalable applications with ease.
Credits: This article is inspired by section 10 - Thinking in React of Jonas Schmedtmann of his React Course on Udemy

