Once you’re comfortable with hooks and basic component composition, React really starts to shine. Advanced patterns help you build scalable, reusable, and maintainable applications without turning your codebase into a mess.
Let’s explore some powerful React patterns used in real-world applications.
1. Compound Components
What it is:
Components that work together and share implicit state.
Example:
<Tabs>
<Tabs.List>
<Tabs.Trigger value="profile" />
<Tabs.Trigger value="settings" />
</Tabs.List>
<Tabs.Content value="profile" />
<Tabs.Content value="settings" />
</Tabs>
Why it’s useful:
- Clean API
- Flexible UI structure
- Better separation of concerns
2. Custom Hooks for Shared Logic
What it is:
Extracting logic into reusable hooks.
Example:
function useFetch(url) {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url).then(res => res.json()).then(setData);
}, [url]);
return data;
}
Why it’s useful:
- Reuse logic without repeating code
- Keeps components simple
3. Render Props
What it is:
Passing a function as a prop to control rendering.
Example:
<DataProvider>
{data => <Chart data={data} />}
</DataProvider>
Why it’s useful:
- Full control over rendering
- Highly flexible behaviour
4. Controlled vs Uncontrolled Components
Controlled:
<input value={value} onChange={onChange} />
Uncontrolled:
<input ref={inputRef} />
When to use which:
- Controlled for forms and validation
- Uncontrolled for performance-sensitive inputs
5. Context for Cross-Cutting Concerns
What it is:
Sharing state across deeply nested components.
Use cases:
- Authentication
- Theme
- Feature flags
Tip:
Avoid putting frequently changing values in context to prevent re-renders.
6. Higher-Order Components (HOCs)
What it is:
Functions that enhance components.
const withAuth = Component => props => (
isAuth ? <Component {...props} /> : <Login />
);
Use sparingly, hooks are often cleaner.
7. Memoization for Performance
Tools:
React.memouseMemouseCallback
Rule:
Optimise only after measuring performance issues.
8. Error Boundaries
What it is:
Catching runtime errors in the UI.
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() {
return { hasError: true };
}
render() {
return this.state.hasError ? <Fallback /> : this.props.children;
}
}
Why it’s useful:
Prevents entire app crashes.
9. Feature-Based Folder Structure
Instead of:
components/
hooks/
utils/
Use:
features/
auth/
dashboard/
billing/
Scales much better for large apps.
10. Controlled Side Effects
Keep effects:
- Small
- Focused
- Predictable
Avoid mixing business logic with rendering logic.
Conclusion
Advanced React patterns aren’t about clever tricks, they’re about clarity, scalability, and maintainability. Use these patterns to build systems that grow gracefully as your app and team expand.
Top comments (0)