Advanced React Patterns: A Practical Guide for Modern Web Apps
Component Patterns
1.1 Compound Components (Context-powered composition)
The compound component pattern is a staple for building UI systems with flexible APIs (e.g., Tabs, Modals). Internally, it uses context to manage shared state between parent and child components.
Use cases:
- ShadCN Tabs, Accordions, Dropdowns .
- Design systems where consumers should customize layout but not logic

1.2 Render Props (Encapsulated logic, render flexibility)
The render props pattern is useful when you need to reuse behavior but allow consumers to customize rendering logic.
Use case: Format chat messages based on type (text, image, file)

Notes:
- Not compatible with hooks inside HOC body (no hook nesting).
- Can abstract shared control logic like guards, layout, and permissions
- Should be pure (no side-effects inside wrapper)
1.3 Higher-Order Components (Behavior wrappers)
HOCs are functions that enhance a component by wrapping it and injecting logic (e.g., conditionally render, modify props).
Use case: Format chat messages based on type (text, image, file)

Good for:
- Behavior reuses with layout control .
- Dynamic UI factories (e.g., animation, formatting, sorting)
Avoid nesting multiple render props—it becomes unreadable fast. Often replaced by hooks today, but still valid when rendering must be deferred to the consumer.
2. State Management Patterns
2.1 Context + useReducer (Controlled global state with transitions)
React’s Context + useReducer is a clean way to manage global or shared state with predictable transitions.
Suitable for:
- Auth flows
- Message lifecycle.
- Application-wide theme/language settings

Wrap this in a context provider and expose via a custom hook for clean access.
2.2 State Collocation (Keep state close to where it’s used)
Context is often overused. Not all states should be global. Use colocation as the default.
Bad (Overlifted):

Better (Collocated):

Rule of thumb:
- If only one component uses the state → keep it local
- If multiple deeply nested components depend on it → lift to context
3. Custom Hooks
Custom hooks are simply reusable logic containers. When state, side-effects, and lifecycle logic repeat across components, extract them into a hook.
Examples:
- useChatInputMachine() → wraps useReducer for message send state machine
- useChatMessages() → listens for socket events
- useScrollToBottom() → manages scroll behavior on new message render

Custom hooks = functional abstraction. Treat them like testable, isolated services inside components.
Closing Note
“You don’t need every pattern. You need to understand when complexity demands it. Good code isn’t clever — it’s clear.”
Learning these patterns has helped me write cleaner, faster React code — and I hope it helps you too. Start small. Refactor one component. You’ll feel the difference.