This project demonstrates common problems and their solutions using modern React/Next.js patterns.
- The homepage groups each problem with its relevant solutions for quick discovery.
- Each problem page lists all of its solution approaches with links.
- Each solution page links back to the original problem and to alternative solutions.
Compare four different solution approaches side-by-side:
- Solution 1: Variant Pattern —
/problems/problem-2 - Solution 2: Composition Pattern —
/problems/problem-3 - Solution 3: Config Object —
/problems/problem-4 - Solution 4: Compound Components —
/problems/problem-5
All solutions in this project apply these 6 fundamental patterns:
Breaking down large components into smaller, focused pieces that handle one responsibility.
Creating a parent component with sub-components that work together, allowing flexible composition.
Instead of spreading props everywhere, group related props into logical config objects.
Building complex UIs by composing smaller, reusable components rather than using conditional props.
Each component should have a single, well-defined responsibility.
Using named slots (sub-components) to allow flexible content placement while maintaining structure.
Patterns Applied: ✅ Specialized Components, ✅ Compound Components, ✅ Config Objects, ✅ Composition, ✅ Separation of Concerns, ✅ Slots
Components with 15+ boolean props to handle different states and variations.
Solution: Variant Pattern + Composition + Config Objects
How Patterns Are Applied:
- Specialized Components: Separate Header, Content, Footer, StateMessage components
- Compound Components: Form.Header, Form.Content, Form.Footer sub-components
- Config Objects: Group display, state, and style props into config object
- Composition: Use children and slots instead of conditional rendering
- Separation of Concerns: Each component handles one responsibility
- Slots Pattern: Named slots for flexible content placement
Patterns Applied: ✅ Specialized Components, ✅ Config Objects, ✅ Composition, ✅ Separation of Concerns
Uses a single variant prop instead of multiple booleans.
How Patterns Are Applied:
- Specialized Components: Separate components for each variant
- Config Objects: Variant config groups related styling
- Composition: Compose variant-specific sub-components
- Separation of Concerns: Each variant has its own component
Patterns Applied: ✅ Specialized Components, ✅ Compound Components, ✅ Composition, ✅ Separation of Concerns, ✅ Slots
Breaks components into smaller, composable pieces.
How Patterns Are Applied:
- Specialized Components: FormHeader, FormContent, FormFooter
- Compound Components: Form.* sub-components
- Composition: Build complex forms from simple pieces
- Separation of Concerns: Each piece has one job
- Slots Pattern: Named slots for content
Patterns Applied: ✅ Config Objects, ✅ Specialized Components, ✅ Separation of Concerns
Groups related props into a single configuration object.
How Patterns Are Applied:
- Config Objects: All props grouped into config
- Specialized Components: Config determines which components render
- Separation of Concerns: Config handles all concerns
Patterns Applied: ✅ Compound Components, ✅ Specialized Components, ✅ Slots, ✅ Composition, ✅ Separation of Concerns
Uses the compound component pattern for maximum flexibility.
How Patterns Are Applied:
- Compound Components: Parent with multiple sub-components
- Specialized Components: Each sub-component is specialized
- Slots Pattern: Sub-components act as named slots
- Composition: Flexible arrangement of sub-components
- Separation of Concerns: Each sub-component has one role
Patterns Applied: ✅ Composition, ✅ Separation of Concerns
Passing props through multiple levels of components that don't use them.
Solution: Context API + Custom Hooks + Composition
How Patterns Are Applied:
- Composition: Use Context to avoid prop drilling
- Separation of Concerns: Context handles data flow separately
Patterns Applied: ✅ Config Objects, ✅ Separation of Concerns
Props that create invalid combinations (e.g., disabled={true} + required={true}).
Solution: Discriminated Unions + Type Safety
How Patterns Are Applied:
- Config Objects: State config prevents conflicts
- Separation of Concerns: Each state is mutually exclusive
Patterns Applied: ✅ Config Objects, ✅ Composition, ✅ Separation of Concerns
Too many callback/handler props cluttering the component.
Solution: Event Object Pattern + Custom Hooks
How Patterns Are Applied:
- Config Objects: Group callbacks into event object
- Composition: Use custom hooks for logic
- Separation of Concerns: Handlers separated from UI
Patterns Applied: ✅ Specialized Components, ✅ Separation of Concerns
Spreading unknown props without control, creating hidden dependencies.
Solution: Explicit Prop Forwarding + Prop Whitelisting
How Patterns Are Applied:
- Specialized Components: Each component explicitly defines props
- Separation of Concerns: Clear prop boundaries
Patterns Applied: ✅ Composition, ✅ Separation of Concerns
Props that should be internal component state.
Solution: Controlled vs Uncontrolled Pattern + Custom Hooks
How Patterns Are Applied:
- Composition: Use custom hooks for state logic
- Separation of Concerns: State management separated from UI
Patterns Applied: ✅ Config Objects, ✅ Specialized Components, ✅ Separation of Concerns
Props that must be used together or depend on each other.
Solution: Group Related Props + Config Objects
How Patterns Are Applied:
- Config Objects: Related props grouped together
- Specialized Components: Each config type has its component
- Separation of Concerns: Each concern is independent
Patterns Applied: ✅ Config Objects, ✅ Separation of Concerns
Weak typing that allows invalid prop values at compile time.
Solution: Strict TypeScript Types + Zod Validation
How Patterns Are Applied:
- Config Objects: Type-safe config objects
- Separation of Concerns: Validation separated from logic
Patterns Applied: ✅ Composition, ✅ Separation of Concerns
Mixing server actions with client handlers creates confusion.
Solution: Clear separation between server and client logic
How Patterns Are Applied:
- Composition: Server actions in separate layer
- Separation of Concerns: Server logic separate from client UI
Patterns Applied: ✅ Composition, ✅ Separation of Concerns
Passing hook results through props instead of using hooks directly.
Solution: Custom Hooks + Composition
How Patterns Are Applied:
- Composition: Use custom hooks directly in components
- Separation of Concerns: Logic in hooks, UI in components
Patterns Applied: ✅ Composition, ✅ Separation of Concerns
Handling async data in props is problematic.
Solution: Server Components + Async/Await
How Patterns Are Applied:
- Composition: Async logic in Server Components
- Separation of Concerns: Data fetching separate from rendering
Patterns Applied: ✅ Composition, ✅ Separation of Concerns
Extracting logic into custom hooks instead of passing callbacks.
Solution: Custom Hooks + Composition
How Patterns Are Applied:
- Composition: Logic extracted to reusable hooks
- Separation of Concerns: Logic separate from UI
| Problem | Specialized | Compound | Config | Composition | Separation | Slots |
|---|---|---|---|---|---|---|
| 1. Too Many Props | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| 2. Variant Pattern | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ |
| 3. Composition | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
| 4. Config Objects | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
| 5. Compound Components | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
| 6. Prop Drilling | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| 7. Conflicting Props | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ |
| 8. Callback Hell | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ |
| 9. Spread Props | ✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
| 10. State vs Props | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| 11. Prop Coupling | ✅ | ❌ | ✅ | ❌ | ✅ | ❌ |
| 12. Type Safety | ❌ | ❌ | ✅ | ❌ | ✅ | ❌ |
| 13. Server Actions | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| 14. Hook Drilling | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| 15. Async Props | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| 16. Custom Hooks | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
- Always use TypeScript - Catch errors at compile time
- Group related props - Use config objects or compound components
- Avoid prop drilling - Use Context API or custom hooks
- Be explicit - Don't spread unknown props
- Separate concerns - Use composition to break down complexity
- Document prop relationships - Use types to make dependencies clear
- Validate at boundaries - Use Zod or similar for runtime validation
- Test prop combinations - Ensure only valid combinations work
- Start with TypeScript - Strict types prevent most issues
- Use Composition - Break components into smaller pieces
- Add Variants - Define clear states
- Group Props - Use config objects for related props
- Use Context - Only when necessary to avoid prop drilling
- Validate - Add Zod validation for complex props
All solutions in this project demonstrate how to apply the 6 core design patterns to solve real-world component prop problems. The key is understanding which patterns to apply for each specific problem:
- Composition + Variants is the most flexible and maintainable for most cases
- Strict TypeScript should always be used
- Context API should be used sparingly for deeply nested data
- Config Objects should group related props
- Discriminated Unions should prevent invalid combinations
- Specialized Components should handle single responsibilities
- Compound Components should provide maximum flexibility
- Slots Pattern should enable content customization
Start with these principles and adjust based on your component's complexity and use cases.