Component composition is a core concept in React that allows you to build complex user interfaces from small, reusable components. Just like in traditional object-oriented programming where objects are composed to create more complex functionality, React encourages composing components together to build a scalable and maintainable UI. Understanding component composition helps you to create more modular, readable, and maintainable code by separating concerns into distinct pieces.
At its core, component composition means that one component is built using one or more other components. The idea is to reuse smaller components to build a larger, more complex user interface.
In the simplest form, component composition happens when a parent component renders one or more child components. Let’s look at a very basic example of component composition.
import React from 'react';
const Header = () => Welcome to My Website
;
const Footer = () => ;
const Page = () => {
return (
This is the main content of the page.
);
};
export default Page;
Page
component composes the UI by rendering the Header
and Footer
components along with a paragraph of content.Header
and Footer
components can be reused in other parts of the application if needed.
Welcome to My Website
This is the main content of the page.
© 2024 My Website
Props (short for properties) are the way data is passed from parent components to child components in React. They allow for dynamic content and customization, making component composition flexible and powerful.
import React from 'react';
const Header = ({ title }) => {title}
;
const Footer = ({ year }) => ;
const Page = () => {
return (
This is the main content of the page.
);
};
export default Page;
Header
component receives the title
prop, and the Footer
component receives the year
prop. This allows each child component to display customized content based on the parent’s data.Header
and Footer
components with different titles and years in other parts of the app.
Welcome to My Website
This is the main content of the page.
© 2024 My Website
In React, props.children
allows components to be more flexible by letting you pass components or elements from the parent to the child, which can be rendered inside the child component.
import React from 'react';
const Card = ({ children }) => {
return (
{children}
);
};
const Page = () => {
return (
This is a Card Title
This is some content inside the card.
);
};
export default Page;
Card
component doesn’t define specific content to render. Instead, it uses props.children
to render whatever is passed between its opening and closing tags when used.Card
component can be reused with different content, making it highly flexible.
This is a Card Title
This is some content inside the card.
A Higher-Order Component (HOC) is a function that takes a component and returns a new component with additional behavior or props. It’s a powerful pattern for reusing component logic.
import React from 'react';
const withGreeting = (WrappedComponent) => {
return (props) => (
Hello, welcome to the app!
);
};
const Content = () => This is the main content.
;
const ContentWithGreeting = withGreeting(Content);
const Page = () => {
return (
);
};
export default Page;
withGreeting
function is an HOC. It takes the Content
component and wraps it with a greeting message. The new component (ContentWithGreeting
) now displays the greeting before rendering the original content.withGreeting
HOC to wrap other components, making it easy to add common behavior across multiple components.
Hello, welcome to the app!
This is the main content.
Render Props is a technique for sharing code between components by using a prop whose value is a function. This function dictates what the component should render.
import React from 'react';
const DataProvider = ({ render }) => {
const data = { name: 'John', age: 25 };
return {render(data)};
};
const Page = () => {
return (
(
User Information
Name: {data.name}
Age: {data.age}
)} />
);
};
export default Page;
DataProvider
component receives a render
prop, which is a function. This function is called inside DataProvider
, allowing it to dictate what is rendered based on the data passed to it.
User Information
Name: John
Age: 25
The Context API in React allows you to share data between components without explicitly passing props down every level of the component tree. It’s an excellent tool for avoiding “prop drilling.”
import React, { createContext, useContext } from 'react';
const UserContext = createContext();
const UserInfo = () => {
const user = useContext(UserContext);
return (
User Information
Name: {user.name}
Age: {user.age}
);
};
const Page = () => {
const user = { name: 'Alice', age: 30 };
return (
);
};
export default Page;
UserContext
is created using createContext
. The Page
component provides the user data to all components inside the UserContext.Provider
via the value
prop.UserInfo
component consumes the UserContext
using the useContext
hook, allowing it to access the user data without needing to pass it down as a prop.
User Information
Name: Alice
Age: 30
The slot pattern allows for more flexibility by letting you pass different components to “slots” inside a parent component.
import React from 'react';
const Layout = ({ header, content, footer }) => {
return (
{header}
{content}
);
};
const Page = () => {
return (
My Website}
content={This is the main content of the page.
}
footer={}
/>
);
};
export default Page;
Layout
component accepts header
, content
, and footer
props, allowing the parent component to pass in different components or elements to these slots.
My Website
This is the main content of the page.
© 2024 My Website
Component composition is a powerful concept in React that allows you to create complex UIs from small, reusable parts. By leveraging techniques such as props, children, higher-order components, render props, and the Context API, you can build scalable, maintainable applications. Advanced patterns like the slot pattern further enhance flexibility, allowing developers to build reusable, dynamic components. Happy Coding!❤️