Introduction
React is one of the most popular frontend libraries, known for its component-based architecture. However, as applications grow, managing reusability, state, and structure becomes challenging. This is where design patterns come in. In this blog, we’ll explore three essential React patterns: Higher-Order Components (HOC), Render Props, and Compound Components. These patterns help in writing scalable and maintainable code.
1️⃣ Higher-Order Components (HOC)
What is a Higher-Order Component?
A Higher-Order Component (HOC) is a function that takes a component and returns an enhanced component with additional functionality. HOCs are great for code reuse and logic abstraction.
Example: Logging User Activity with an HOC
import React from "react";
// Higher-Order Component
function withLogger(WrappedComponent) {
return function EnhancedComponent(props) {
console.log(`Component ${WrappedComponent.name} rendered!`);
return <WrappedComponent {...props} />;
};
}
// Regular Component
function Button({ label }) {
return <button>{label}</button>;
}
// Enhanced Component
const ButtonWithLogger = withLogger(Button);
export default function App() {
return <ButtonWithLogger label="Click Me" />;
}
When to Use HOCs?
✅ Authentication & Authorization
✅ Logging & Analytics
✅ Data Fetching & Caching
2️⃣ Render Props
What is Render Props?
A Render Prop is a function passed as a prop to a component. The child component then calls this function to render dynamic content. This pattern is helpful when sharing logic between components.
Example: Mouse Tracker Component
import React, { useState } from "react";
// Component using Render Props
function MouseTracker({ render }) {
const [position, setPosition] = useState({ x: 0, y: 0 });
const handleMouseMove = (event) => {
setPosition({ x: event.clientX, y: event.clientY });
};
return <div onMouseMove={handleMouseMove}>{render(position)}</div>;
}
// Using MouseTracker in App
export default function App() {
return (
<MouseTracker
render={({ x, y }) => (
<h2>
Mouse Position: ({x}, {y})
</h2>
)}
/>
);
}
When to Use Render Props?
✅ Handling state across multiple components
✅ Animation effects
✅ Form handling
3️⃣ Compound Components
What is a Compound Component?
A Compound Component is a pattern where multiple components work together as a single unit, allowing for a clean and flexible API. This pattern is useful for designing reusable UI components like tabs, modals, and accordions.
Example: Custom Tabs Component
import React, { useState } from "react";
function Tabs({ children }) {
const [activeIndex, setActiveIndex] = useState(0);
return React.Children.map(children, (child, index) => {
if (child.type === TabList) {
return React.cloneElement(child, { activeIndex, setActiveIndex });
}
if (child.type === TabPanel) {
return activeIndex === index - 1 ? child : null; // Only show active panel
}
return child;
});
}
function TabList({ children, activeIndex, setActiveIndex }) {
return React.Children.map(children, (child, index) =>
React.cloneElement(child, {
isActive: activeIndex === index,
onClick: () => setActiveIndex(index),
})
);
}
function Tab({ children, isActive, onClick }) {
return (
<button onClick={onClick} style={{ fontWeight: isActive ? "bold" : "normal" }}>
{children}
</button>
);
}
function TabPanel({ children }) {
return <div>{children}</div>;
}
// Usage
export default function App() {
return (
<Tabs>
<TabList>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
</TabList>
<TabPanel>Content of Tab 1</TabPanel>
<TabPanel>Content of Tab 2</TabPanel>
</Tabs>
);
}
When to Use Compound Components?
✅ Tabs & Accordions
✅ Modals & Dialogs
✅ Dropdown Menus
Conclusion
React Design Patterns help in writing scalable, reusable, and maintainable code. Here's a quick summary:
Pattern | Use Case | Example |
---|---|---|
Higher-Order Components (HOC) | Code reuse, authentication, analytics | withLogger(Component) |
Render Props | Dynamic UI rendering, sharing state | {render: (props) => <Component {...props} />} |
Compound Components | Designing flexible, reusable UI components | <Tabs><TabList><Tab /></TabList><TabPanel /></Tabs> |
Each pattern has its strengths, and choosing the right one depends on the problem you are solving. Mastering these patterns will make you a better React developer! 🚀
Which pattern do you use the most? Let me know in the comments! 👇
Top comments (1)
Nice examples, especially of the compound components pattern. I would like to add though that you should be really careful with render props, because what you put in them can very easily result in very bad performing react code, unless you properly memoize everything.
In general it is recommended to use custom hooks instead of render props and HoCs.