Exploring Advanced React Patterns: Compound Components, Render Props, and Hooks

Harry Bloch
3 min readMay 19, 2023

--

Hello React enthusiasts and devoted learners! It’s time to take another deep dive into the world of React. Today, we’re going to unravel some advanced React patterns: Compound Components, Render Props, and Hooks. By understanding and leveraging these patterns, you can supercharge your React development skills and create more robust and scalable applications.

Don’t miss out on more content like this — be sure to follow me on Twitter and Medium for more insights into the wonderful world of React.

Compound Components

Compound Components is a design pattern in which components are used together, such that they share an implicit state, allowing you to write more declarative and flexible APIs. The most common example would be the <select> and <option> elements in HTML.

In React, a typical implementation might look like this:

function Tabs({ children }) {
const [activeTab, setActiveTab] = useState(children[0].props.label);

return (
<div>
{React.Children.map(children, child => {
return React.cloneElement(child, {
isActive: child.props.label === activeTab,
setActiveTab
});
})}
</div>
);
}

function Tab({ label, isActive, setActiveTab, children }) {
return (
<div onClick={() => setActiveTab(label)}>
{isActive && children}
</div>
);
}

Here, the Tabs component shares its state with its Tab children, controlling which tab is active.

Render Props

Render Props is a technique in React for sharing code between components using a prop whose value is a function. It’s a great pattern for reusing behavior between components. A good example is a MouseTracker component that tracks mouse position:

class MouseTracker extends React.Component {
constructor(props) {
super(props);
this.state = { x: 0, y: 0 };
}

handleMouseMove = (event) => {
this.setState({
x: event.clientX,
y: event.clientY
});
}

render() {
return (
<div onMouseMove={this.handleMouseMove}>
{this.props.render(this.state)}
</div>
);
}
}

Here, any component that needs to know the mouse position can use MouseTracker and provide a render prop function to customize what it wants to render with that state.

Hooks

Hooks, introduced in React 16.8, allow you to use state and other React features without writing a class. They let you reuse stateful logic between components, breaking complex components into smaller functions based on what pieces are related.

Here’s a basic example of using the useState and useEffect hooks:

function Example() {
const [count, setCount] = useState(0);

useEffect(() => {
document.title = `You clicked ${count} times`;
});

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

In this example, useState and useEffect let us add state and side effects (respectively) to our functional component.

Remember, when it comes to hooks, there’s so much more than useState and useEffect. Don't forget about other built-in hooks like useContext, useReducer, and useRef, and remember that you can also create your own custom hooks!

Conclusion

Advanced React patterns like Compound Components, Render Props, and Hooks truly unlock a new level of power and flexibility in our applications. They allow us to create more reusable, scalable, and maintainable code, which is crucial for growing applications.

Compound Components offer a declarative API and greater flexibility, Render Props help share behavior across components, and Hooks let us use state and lifecycle methods in functional components, as well as extract component logic into reusable functions.

However, as with all things in programming, these come with their own trade-offs. They may add complexity to the code, and understanding how they work can require a steep learning curve. That being said, once mastered, these patterns can significantly improve your codebase and your efficiency as a React developer.

As always, the best way to learn is by doing. Try integrating these patterns into your next project or take an existing project and see how you could refactor it using these advanced patterns. You’ll likely find that these powerful patterns can make your code cleaner, easier to read, and more fun to write.

If you found this guide helpful, don’t forget to follow me on Twitter and Medium for more in-depth guides and insights into the world of React development. Stay curious, keep learning, and happy coding!

Next time, we will continue our journey into advanced React topics, exploring even more patterns and best practices to make your React code shine. Don’t miss it! Until then, keep building incredible things.

--

--