FrontendReactComponent PatternsCompositionArchitectureTypeScript

React Component Composition: Advanced Patterns for Reusable UI

Master React composition patterns — compound components, render props, slots, and headless components — for building truly reusable UI.

Abdur Razzak

Abdur Razzak

Full-Stack Web Developer

December 23, 2024 10 min read

Why Composition Over Inheritance

React's component model is built around composition, not inheritance. Rather than extending a base component class, you compose behavior by nesting components and passing props. This leads to more flexible, testable, and maintainable code. Advanced composition patterns let you build component APIs that are easy to use correctly and hard to use incorrectly.

Compound Components Pattern

The compound component pattern groups related components under a parent namespace: Tabs.List, Tabs.Tab, Tabs.Panel. These components share implicit state via React Context, so the parent Tabs component manages active state without the consumer needing to wire it up manually. Libraries like Radix UI and React Aria use this pattern extensively. Implement it with createContext and useContext inside a parent component.

Render Props and Function Children

Render props pass a function as a prop or as children, letting the consumer control rendering while the parent component manages behavior. A DataFetcher component that accepts children as a function can call children({ data, loading, error }) with the fetched state. This pattern predates hooks but is still useful for complex renderless logic. Hooks have replaced most render prop use cases, but function children remain valuable for layout flexibility.

Headless Components

Headless components provide behavior and accessibility without any visual output — the consumer provides the UI. Libraries like Radix UI Primitives, React Aria, and Headless UI are built on this pattern. You get perfect keyboard behavior, ARIA attributes, and screen reader support without any styling opinions. Apply your own Tailwind classes or CSS to get your exact visual design without fighting the library's default styles.

Slot Pattern with children and React.Children

The slot pattern lets consumers place content in specific named positions within a parent component — similar to Vue's named slots. Implement it by defining separate prop names for each slot: header, footer, sidebar. Or use React.Children.map() to filter children by type, placing each in its appropriate position. This gives consumers control over what renders in each region of the layout component.

Context + Composition for Scalable APIs

The most scalable React component APIs combine Context (for shared state) with Composition (for flexible rendering). Build a Form component that tracks validation state via Context, child Input components that read their error state from Context automatically, and a FormSubmitButton that disables itself when validation fails — all without prop drilling. This pattern produces clean, self-contained component libraries.

Share this article

All posts
#React#Component Patterns#Composition#Architecture#TypeScript
Abdur Razzak — Full Stack Web Developer
⭐ Top Rated

Upwork Top Rated Developer

Work With a Developer Clients Trust