React Component Structure AI Prompts for Frontend Engineers
React applications grow in complexity. What starts as a simple component hierarchy becomes a tangle of props passed through layers that do not need them, state duplicated across unrelated components, and side effects scattered throughout the codebase.
The problems are predictable. Prop drilling happens when components need data they do not own. State management becomes chaotic when components manage their own state that should be shared. Component boundaries blur when logic and presentation mix.
The solutions are also predictable. Context, composition, custom hooks, state machines. The challenge is knowing which solution applies when, and how to refactor existing code without breaking everything.
AI can help you think through these architectural decisions and generate refactoring code. It cannot replace your judgment about whether the architecture is right.
AI Unpacker provides prompts designed to help frontend engineers solve common React architectural challenges.
TL;DR
- Prop drilling is a design smell, not an inevitability.
- Component composition is often better than prop passing.
- Custom hooks encapsulate logic without creating state management overhead.
- Context is powerful but not free — know when to use it.
- State machines prevent impossible states in complex UIs.
- Refactoring is safer with tests, but you can refactor without them.
Introduction
React is unopinionated about architecture. That flexibility is a feature. It is also a trap. Without conventions, React applications accumulate architectural debt faster than business logic.
The symptoms are familiar. A prop changes and you have to update six components. Two developers implement similar features with completely different approaches. A feature works in development but fails in production because of timing issues. State updates seem to happen in the wrong order.
These are not React problems. These are architecture problems. React gives you the primitives. You have to build the structure.
1. Prop Drilling Diagnosis and Solutions
Prop drilling happens when data flows through components that do not need it, just to reach components that do. It makes components fragile and harder to understand.
Prompt for Prop Drilling Analysis
Diagnose prop drilling issue and recommend solutions.
Current code structure:
App
└── Dashboard
└── Sidebar
└── Navigation
└── UserMenu (needs user.name and user.avatar)
Problem:
- UserMenu needs user data
- Currently passed through: Dashboard → Sidebar → Navigation → UserMenu
- Intermediate components (Sidebar, Navigation) do not use user data
- When user data changes, all intermediate components re-render
What I know:
- User data comes from authentication context
- UserMenu also needs logout function
- UserMenu is used in one place only
- App is being migrated to TypeScript
What I need:
1. Should I use Context, pass props, or use composition?
2. How do I refactor without breaking existing functionality?
3. TypeScript types for the recommended approach
4. How to handle the logout function?
Solution options:
Option 1: Prop drilling (current)
- Pros: Explicit, easy to trace
- Cons: Fragile, unnecessary re-renders
Option 2: Context
- Pros: Clean syntax, no drilling
- Cons: Harder to optimize, implicit dependencies
Option 3: Composition (pass component as prop)
- Pros: Flexible, explicit
- Cons: Requires restructuring
Option 4: Custom hook
- Pros: Encapsulates logic, reusable
- Cons: Does not solve prop drilling directly
Tasks:
1. Analyze which solution fits this scenario
2. Generate code for the recommended approach
3. Show before/after comparison
4. Define TypeScript interfaces
5. Suggest testing approach
Generate prop drilling solution with code examples.
2. State Management Architecture
State management decisions early in a project have outsized impact later. The right architecture depends on the complexity of the state and how components interact with it.
Prompt for State Management Strategy
Design state management approach for this feature.
Feature: Multi-step form wizard (5 steps)
- Step 1: Basic info (name, email)
- Step 2: Company info (company, role, team size)
- Step 3: Preferences (notifications, theme)
- Step 4: Review (read-only summary)
- Step 5: Confirmation (success message)
Requirements:
- User can navigate back and forth between steps
- Data persists if user leaves and returns
- Form data needed on final confirmation
- Each step validates before proceeding
- Some fields conditionally shown based on earlier answers
Current state:
- Using local component state (useState)
- Step 1 works, concerned about scale
- No persistence yet (data lost on refresh)
- Will need to integrate with API eventually
State management options:
Option 1: Component state (current)
- Pros: Simple, no setup
- Cons: Prop drilling, no persistence, hard to debug
Option 2: Context + useReducer
- Pros: Shares state without props, predictable updates
- Cons: Boilerplate, requires provider setup
Option 3: URL state
- Pros: Shareable, browser history works, persistence built-in
- Cons: Security concerns for sensitive data, URL complexity
Option 4: Third-party (Zustand, Jotai, Redux)
- Pros: Powerful devtools, ecosystem
- Cons: Overhead, learning curve
What I need to understand:
1. Which approach scales best for this complexity?
2. How to handle form persistence?
3. How to structure validation?
4. How to prepare for API integration?
Tasks:
1. Recommend state management architecture
2. Generate code structure with the recommended approach
3. Define state shape and actions
4. Show how validation fits into the architecture
5. Outline API integration plan
Generate state management architecture with code examples.
3. Component Composition Patterns
The best React code uses composition. Components that do one thing well, and compose to build complex UIs. This is harder to design than it sounds.
Prompt for Component Composition Design
Design component composition for this UI.
UI: Social media post component
Elements:
1. Post header (avatar, name, timestamp, menu)
2. Post content (text, optional image, optional link preview)
3. Engagement bar (like, comment, share buttons with counts)
4. Comment section (collapsible, shows top 2 + "view all")
Requirements:
- Post content can be text only, image only, or mixed
- Link preview fetched from URL if post contains link
- Like button has optimistic update
- Comments lazy-load when section opens
- Menu has different options based on post ownership
Current approach:
- Single Post component (600+ lines)
- Props: post object with all data
- Uses useEffect for link preview fetching
- All state in component
Composition opportunities:
- Header as separate component
- Content broken into TextPost, ImagePost, LinkPost
- EngagementBar as separate component
- CommentSection as separate component
- Menu as separate component
What I need:
1. How to structure the component hierarchy?
2. Where should state live vs props?
3. How to handle the optional elements (conditional rendering)?
4. How to avoid prop drilling through Content components?
5. TypeScript type definitions for each component?
Deliverables:
1. Component hierarchy diagram (text-based)
2. Props interfaces for each component
3. Code for main Post component
4. Code for at least one Content variant
5. Hook recommendations for shared logic
Tasks:
1. Define component boundaries
2. Design props interface hierarchy
3. Generate component code structure
4. Identify shared logic for hooks
5. Create TypeScript interfaces
Generate component composition design with code examples.
4. Side Effect Management
Side effects are where React applications get messy. Data fetching, subscriptions, manual DOM manipulation. They do not belong in components, but where do they belong?
Prompt for Side Effect Architecture
Architect side effect handling for data fetching.
Feature: User dashboard with multiple data sources
Data sources:
1. User profile (small, rarely changes)
2. User's projects list (medium, changes on project creation/deletion)
3. Activity feed (large, paginated, changes frequently)
4. Notifications (small, changes frequently)
Current problems:
- useEffect with data fetching in each component
- No loading states handled consistently
- Error handling is ad-hoc
- Race conditions when switching between tabs quickly
- No cache invalidation strategy
What I need:
1. Where should data fetching logic live?
2. How to handle loading and error states consistently?
3. How to prevent race conditions?
4. Cache invalidation strategy
5. How to prepare for React Server Components?
Approaches to consider:
Custom hooks per resource:
- Pros: Reusable, testable, explicit
- Cons: Repeatable boilerplate
Data fetching library (TanStack Query, SWR):
- Pros: Built-in caching, deduplication, error handling
- Cons: Additional dependency, learning curve
Context for server state:
- Pros: React-native, shareable
- Cons: Custom implementation needed
Server Components (future):
- Pros: No client-side fetching
- Cons: Not ready for production use yet
Tasks:
1. Recommend data fetching architecture
2. Define loading and error state patterns
3. Show implementation for Activity feed (most complex)
4. Create custom hook template for other resources
5. Document cache invalidation approach
Generate side effect architecture with implementation examples.
FAQ
When should I use Context vs props?
Use Context when multiple components at different nesting levels need the same data and you do not want to pass it through every intermediate component. Use props when the data is only needed by components in a localized subtree. Context is not free — it creates implicit dependencies that can be harder to trace than props.
How do I know when to extract a custom hook?
Extract a custom hook when you have logic that is reused across multiple components, or when a component’s render logic is obscured by data-fetching or effect code. Good custom hooks do one thing. If your hook is doing multiple things, split it. If your component does not use the hook anymore after extraction, the extraction was worth it.
What is the right level of component granularity?
There is no formula. The right level is the level that makes your code understandable and maintainable. Components that are too large do too much. Components that are too small create indirection without abstraction. When you are deciding whether to split a component, ask: would splitting this make the code easier to understand or test? If yes, split it.
How do I refactor without tests?
Carefully. Start with the leaves of the component tree. Refactor the components that have no components depending on them. Work inward. After each refactor, manually test that the component still works. Commit after each successful refactor. If you break something, you want a small surface area to debug.
Conclusion
React architecture is not about using the latest patterns. It is about using patterns that match the complexity of your application. Simple applications can use props and local state. Complex applications need composition, context, and thoughtful state management.
AI Unpacker gives you prompts to think through architectural decisions and generate refactoring code. But the judgment about what architecture fits your situation, and the care to refactor without breaking things — those come from you.
The goal is not clever code. The goal is code that you and your team can understand, maintain, and extend.