---
name: component-patterns
description: "React/Next.js component design pattern library. Provides Compound/Render Props/HOC/Custom Hooks patterns, state management strategies (Zustand/React Query/Context), and folder structure conventions as a frontend-dev extension skill. Use for requests like 'component patterns', 'React patterns', 'state management', 'folder structure', 'Custom Hook', 'component separation', and other frontend architecture design tasks. However, actual code implementation or backend logic is outside this skill's scope."
---
# Component Patterns — React/Next.js Component Design Patterns
A reference for component patterns, state management strategies, and project structure that the frontend-dev agent uses during frontend development.
## Target Agent
`frontend-dev` — Applies this skill's patterns directly to component design and state management.
## Component Design Patterns
### 1. Compound Components
A pattern where parent and child share implicit state.
**Suited for**: Tab, Accordion, Dropdown, Select, and other composite UI
**Structure**: `<Select>` + `<Select.Trigger>` + `<Select.Option>`
**Key Concept**: State sharing via Context, flexible composition through children
### 2. Render Props / Children as Function
Delegates rendering logic externally.
**Suited for**: Data fetching wrappers, mouse/scroll tracking
**Structure**: `<DataLoader render={(data) => <UI data={data} />} />`
**Note**: Prefer Hook pattern when it can replace this
### 3. Custom Hooks (Extraction Pattern)
Extracts state logic into reusable Hooks.
**Suited for**: Form management, API calls, localStorage, debounce
**Naming**: `use` prefix required — `useForm`, `useDebounce`, `useAuth`
### 4. Container/Presentational Separation
Separates data logic (Container) from UI presentation (Presentational).
**Suited for**: Large-scale apps, when testability is needed
**Container**: Data fetch, state management, event handlers
**Presentational**: Renders only from props, functionally pure
### 5. Higher-Order Component (HOC)
Wraps a component to add functionality.
**Suited for**: Auth guards, layout wrappers, error boundaries
**Naming**: `with` prefix — `withAuth`, `withLayout`
**Note**: Prefer Hook/Context when they can replace this
### 6. Headless Component
Provides behavior/state without UI.
**Suited for**: Sharing logic independent of design system
**Examples**: headless `useCombobox`, `useDialog`, `useTable`
## State Management Strategy Selection Guide
| State Type | Recommended Tool | Rationale |
|-----------|-----------------|-----------|
| **UI Local State** | useState, useReducer | Component-internal |
| **Server State** | React Query (TanStack Query) | Caching, refetch, optimistic updates |
| **Global Client State** | Zustand | Concise, minimal boilerplate |
| **Complex Global State** | Zustand + Immer | Immutability convenience |
| **URL State** | nuqs / useSearchParams | Filters, pagination |
| **Form State** | React Hook Form + Zod | Integrated validation |
| **Theme/Language** | Context + Provider | Low change frequency |
### State Placement Decision Flow
```
Should this state be restorable from URL? → URL state
Is it server data? → React Query
Is it shared across multiple components? → Zustand
Is it internal to one component? → useState
Does it have complex transition logic? → useReducer
```
## Next.js App Router Folder Structure
### Recommended Structure (Feature-Based)
```
src/
├── app/ # Next.js App Router
│ ├── (auth)/ # Auth-related route group
│ │ ├── login/page.tsx
│ │ └── register/page.tsx
│ ├── (main)/ # Main route group
│ │ ├── dashboard/page.tsx
│ │ └── settings/page.tsx
│ ├── api/ # API Routes
│ │ └── [...]/route.ts
│ ├── layout.tsx # Root layout
│ └── page.tsx # Home
├── components/
│ ├── ui/ # General UI (Button, Input, Modal)
│ └── features/ # Feature-specific components
│ ├── auth/
│ └── dashboard/
├── hooks/ # Custom Hooks
├── lib/ # Utilities, config
│ ├── api.ts # API client
│ ├── auth.ts # Auth utilities
│ └── utils.ts
├── stores/ # Zustand stores
├── types/ # TypeScript types
└── styles/ # Global styles
```
## Component File Conventions
| Item | Rule |
|------|------|
| File Name | PascalCase: `UserProfile.tsx` |
| Directory | kebab-case: `user-profile/` |
| Index | Re-export via `index.ts` |
| Test | `UserProfile.test.tsx` in same directory |
| Story | `UserProfile.stories.tsx` in same directory |
| Types | Same file or separate `types.ts` |
## Performance Optimization Patterns
| Pattern | When | Tool |
|---------|------|------|
| **Memoization** | Expensive computation, frequent re-renders | `useMemo`, `React.memo` |
| **Lazy Loading** | Initial bundle size | `React.lazy`, `next/dynamic` |
| **Virtualization** | 1000+ item lists | `@tanstack/react-virtual` |
| **Image Optimization** | Image loading | `next/image` |
| **Code Splitting** | Per-route splitting | App Router automatic |
| **Optimistic Updates** | Immediate feedback | React Query `onMutate` |
| **Debounce** | Search, input | `useDeferredValue` or custom hook |
## Error Handling Patterns
### Hierarchical Error Boundaries
```
RootErrorBoundary (global)
└── LayoutErrorBoundary (per section)
└── ComponentErrorFallback (individual)
```
### API Error Handling
| HTTP Status | Client Handling |
|------------|----------------|
| 401 | Auto logout + redirect |
| 403 | Unauthorized UI |
| 404 | Not Found page |
| 422 | Per-field form error display |
| 429 | Retry + wait notice |
| 500 | Generic error UI + retry button |
## Accessibility (a11y) Checklist
- [ ] Alt text on all images
- [ ] Keyboard navigation (Tab, Enter, Escape)
- [ ] ARIA labels (aria-label, role)
- [ ] Color contrast 4.5:1 or above
- [ ] Visible focus indicator
- [ ] Screen reader testing
- [ ] Semantic HTML (button, nav, main, section)