Introduction
React is flexible by design, which means there are many ways to solve the same problem. Over the years, the community has converged on a set of patterns that consistently produce clean, reusable code. Here are 10 patterns worth adding to your toolkit.
1. Compound Components
Compound components let you build a group of components that share implicit state. Think of how HTML's <select> and <option> work together.
function Tabs({ children }) {
const [active, setActive] = useState(0);
return (
<TabsContext.Provider value={{ active, setActive }}>
{children}
</TabsContext.Provider>
);
}
function Tab({ index, children }) {
const { active, setActive } = useContext(TabsContext);
return (
<button className={active === index ? 'active' : ''} onClick={() => setActive(index)}>
{children}
</button>
);
}
2. Custom Hooks for Logic Reuse
Instead of reaching for HOCs or render props, extract stateful logic into a custom hook. This is the most idiomatic React pattern since hooks landed in v16.8.
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(r => r.json())
.then(d => { setData(d); setLoading(false); });
}, [url]);
return { data, loading };
}
3. The Render Props Pattern
A component accepts a function as a prop and calls it with data, giving the consumer full control over what to render. Useful for complex data-sharing scenarios.
4. Control Props Pattern
Allow a component to be both "controlled" (consumer manages state) and "uncontrolled" (component manages its own state). This is how React's native <input> works.
5. Provider Pattern
Use Context to provide data to a subtree without prop drilling. Pair it with a custom hook for a clean API.
Conclusion
These patterns are not rules — they're tools. Use them when they solve a real problem, not for their own sake. The best React code is the simplest code that gets the job done reliably.
Alex Morgan
Senior Full-Stack Engineer
Related Articles
Getting Started with TypeScript in 2025: A Practical Guide
TypeScript is no longer optional for serious JavaScript projects. Here's the fastest path from zero to productive with TS in 2025.
Building Scalable APIs with NestJS: Architecture Guide
NestJS brings Angular-inspired architecture to Node.js. Learn how to structure large APIs with modules, guards, interceptors, and pipes.
Understanding React Server Components: A Deep Dive
React Server Components fundamentally change how we think about rendering. Here's everything you need to know about RSC, with Next.js 14 App Router examples.