moai-ref-react-patterns
GitHub提供React/Next.js组件设计模式、状态管理策略及项目结构参考,涵盖复合组件、自定义钩子、容器/展示分离等生产级前端规范。
Trigger Scenarios
Install
npx skills add modu-ai/moai-adk --skill moai-ref-react-patterns -g -y
SKILL.md
Frontmatter
{
"name": "moai-ref-react-patterns",
"metadata": {
"tags": "react, nextjs, component, patterns, frontend, reference",
"status": "active",
"updated": "2026-03-30",
"version": "1.0.0",
"category": "domain"
},
"description": "React\/Next.js component design patterns, state management strategies, and project structure reference for frontend development. Agent-extending skill that amplifies frontend domain work (spawned via Agent(general-purpose) with frontend instructions) with production-grade React patterns. NOT for: backend API design, database modeling, DevOps, mobile apps.\n",
"when_to_use": "Use for React\/Next.js component design patterns: state-management strategies, hooks, component composition, and project structure. Amplifies frontend domain work (Agent(general-purpose) with frontend instructions) with production-grade React patterns.\n",
"user-invocable": false,
"progressive_disclosure": {
"enabled": true,
"level1_tokens": 100,
"level2_tokens": 3000
}
}
React Patterns Reference
Target Spawn
Frontend domain work spawned via Agent(general-purpose) with frontend instructions - Applies these patterns directly to component design and state management.
Component Design Patterns
1. Compound Components
Parent and child share implicit state via Context.
Suited for: Tab, Accordion, Dropdown, Select
Structure: <Select> + <Select.Trigger> + <Select.Option>
2. Custom Hooks (Extraction Pattern)
Extract state logic into reusable hooks.
Suited for: Form management, API calls, localStorage, debounce
Naming: use prefix required - useForm, useDebounce, useAuth
3. Container/Presentational Separation
Separate data logic (Container) from UI (Presentational).
Suited for: Large apps, when testability is needed Container: Data fetch, state management, event handlers Presentational: Renders only from props, functionally pure
4. Headless Component
Provides behavior/state without UI.
Suited for: Design system-independent logic
Examples: headless useCombobox, useDialog, useTable
State Management Selection Guide
| State Type | Tool | Rationale |
|---|---|---|
| UI Local | useState, useReducer | Component-internal |
| Server State | React Query / TanStack Query | Caching, refetch, optimistic |
| Global Client | Zustand | Concise, minimal boilerplate |
| Complex Global | Zustand + Immer | Immutability convenience |
| URL State | nuqs / useSearchParams | Filters, pagination |
| Form State | React Hook Form + Zod | Integrated validation |
| Theme/i18n | Context + Provider | Low change frequency |
Decision Flow
Restorable from URL? -> URL state (nuqs)
Server data? -> React Query
Shared across components? -> Zustand
Component-internal? -> useState
Complex transitions? -> useReducer
Next.js App Router Structure
src/
├── app/ # App Router
│ ├── (auth)/ # Auth route group
│ │ ├── login/page.tsx
│ │ └── register/page.tsx
│ ├── (main)/ # Main route group
│ │ ├── dashboard/page.tsx
│ │ └── settings/page.tsx
│ ├── api/ # API Routes
│ ├── layout.tsx # Root layout
│ └── page.tsx # Home
├── components/
│ ├── ui/ # Base UI (Button, Input, Modal)
│ └── features/ # Feature components
│ ├── auth/
│ └── dashboard/
├── hooks/ # Custom hooks
├── lib/ # Utilities, config
├── stores/ # Zustand stores
├── types/ # TypeScript types
└── styles/ # Global styles
Component Quality Standards
| Item | Standard |
|---|---|
| Component Size | Under 200 lines (split if exceeded) |
| Props | 5 or fewer (group into object if exceeded) |
| Custom Hooks | Always extract when reusing logic |
| Error Boundaries | Set at the page level |
| Loading States | Provide loading UI for all async ops |
| Form Validation | Validate on both client and server |
Performance Patterns
| Pattern | When | Tool |
|---|---|---|
| Memoization | Expensive computation | useMemo, React.memo |
| Lazy Loading | Bundle size | React.lazy, next/dynamic |
| Virtualization | 1000+ item lists | @tanstack/react-virtual |
| Image Optimization | Image loading | next/image |
| Optimistic Updates | Immediate feedback | React Query onMutate |
| Debounce | Search, input | useDeferredValue or custom hook |
Error Handling
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 |
| 429 | Retry + wait notice |
| 500 | Generic error + retry button |
Accessibility 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
- Semantic HTML (button, nav, main, section)
Common Rationalizations
| Rationalization | Reality |
|---|---|
| "useEffect is fine for data fetching in React 19" | React 19 provides use() and server components for data fetching. useEffect for fetch is a legacy pattern that causes waterfalls. |
| "Global state is simpler than prop drilling" | Global state couples distant components. Prop drilling or composition via children is more predictable and testable. |
| "I will add TypeScript types later" | Untyped components accumulate any-typed callers. Retrofitting types into a used component is much harder than starting typed. |
| "This component does not need memoization" | Premature memoization is waste, but components rendering lists or expensive trees should be profiled, not assumed fast. |
| "CSS-in-JS is fine, everyone uses it" | CSS-in-JS adds runtime overhead and bundle size. Tailwind or CSS Modules achieve the same scoping without the cost. |
Red Flags
- useEffect used for data fetching when server components or use() are available
- Component receives more than 5 props without decomposition or object grouping
- State management library used for server-cacheable data (use React Query or SWR instead)
- Inline styles or hardcoded pixel values instead of design tokens
- Component missing error boundary wrapping for async operations
Verification
- Data fetching uses server components, use(), or React Query (not useEffect + fetch)
- Components have TypeScript interfaces for all props
- Error boundaries wrap components with async operations
- Accessibility checklist completed (alt text, keyboard nav, ARIA, contrast, focus, semantics)
- No inline styles or hardcoded color/spacing values (design tokens used)
- Component renders correctly in React Strict Mode (no double-effect issues)
Version History
- 4100d87 Current 2026-08-20 09:09


