跳至主要内容
小龙虾小龙虾AI
🤖

React

Full React 19 engineering, architecture, Server Components, hooks, Zustand, TanStack Query, forms, performance, testing, production deploy.

下载2.1k
星标2
版本1.0.4
开发工具
安全通过
💬Prompt

技能说明


name: React slug: react version: 1.0.4 homepage: https://clawic.com/skills/react changelog: "Added React 19 coverage, Server Components, AI Mistakes section, Core Rules, state management patterns, setup system" description: Full React 19 engineering, architecture, Server Components, hooks, Zustand, TanStack Query, forms, performance, testing, production deploy.

React

Production-grade React engineering. This skill transforms how you build React applications — from component architecture to deployment.

When to Use

  • Building React components, pages, or features
  • Implementing state management (useState, Context, Zustand, TanStack Query)
  • Working with React 19 (Server Components, use(), Actions)
  • Optimizing performance (memo, lazy, Suspense)
  • Debugging rendering issues, infinite loops, stale closures
  • Setting up project architecture and folder structure

Architecture Decisions

Before writing code, make these decisions:

DecisionOptionsDefault
RenderingSPA / SSR / Static / HybridSSR (Next.js)
State (server)TanStack Query / SWR / use()TanStack Query
State (client)useState / Zustand / JotaiZustand if shared
StylingTailwind / CSS Modules / styledTailwind
FormsReact Hook Form + Zod / nativeRHF + Zod

Rule: Server state (API data) and client state (UI state) are DIFFERENT. Never mix them.

Component Rules

// ✅ The correct pattern
export function UserCard({ user, onEdit }: UserCardProps) {
  // 1. Hooks first (always)
  const [isOpen, setIsOpen] = useState(false)
  
  // 2. Derived state (NO useEffect for this)
  const fullName = `${user.firstName} ${user.lastName}`
  
  // 3. Handlers
  const handleEdit = useCallback(() => onEdit(user.id), [onEdit, user.id])
  
  // 4. Early returns
  if (!user) return null
  
  // 5. JSX (max 50 lines)
  return (...)
}
RuleWhy
Named exports onlyRefactoring safety, IDE support
Props interface exportedReusable, documented
Max 50 lines JSXExtract if bigger
Max 300 lines fileSplit into components
Hooks at topReact rules + predictable

State Management

Is it from an API?
├─ YES → TanStack Query (NOT Redux, NOT Zustand)
└─ NO → Is it shared across components?
    ├─ YES → Zustand (simple) or Context (if rarely changes)
    └─ NO → useState

TanStack Query (Server State)

// Query key factory — prevents key typos
export const userKeys = {
  all: ['users'] as const,
  detail: (id: string) => [...userKeys.all, id] as const,
}

export function useUser(id: string) {
  return useQuery({
    queryKey: userKeys.detail(id),
    queryFn: () => fetchUser(id),
    staleTime: 5 * 60 * 1000, // 5 min
  })
}

Zustand (Client State)

// Thin stores, one concern each
export const useUIStore = create<UIState>()((set) => ({
  sidebarOpen: true,
  toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),
}))

// ALWAYS use selectors — prevents unnecessary rerenders
const isOpen = useUIStore((s) => s.sidebarOpen)

React 19

Server Components (Default in Next.js App Router)

// Server Component — runs on server, zero JS to client
async function ProductList() {
  const products = await db.products.findMany() // Direct DB access
  return <ul>{products.map(p => <ProductCard key={p.id} product={p} />)}</ul>
}

// Client Component — needs 'use client' directive
'use client'
function AddToCartButton({ productId }: { productId: string }) {
  const [loading, setLoading] = useState(false)
  return <button onClick={() => addToCart(productId)}>Add</button>
}
Server ComponentClient Component
async/await ✅useState ✅
Direct DB ✅onClick ✅
No bundle sizeAdds to bundle
useState ❌async ❌

use() Hook

// Read promises in render (with Suspense)
function Comments({ promise }: { promise: Promise<Comment[]> }) {
  const comments = use(promise) // Suspends until resolved
  return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>
}

useActionState (Forms)

'use client'
async function submitAction(prev: State, formData: FormData) {
  'use server'
  // ... server logic
  return { success: true }
}

function Form() {
  const [state, action, pending] = useActionState(submitAction, {})
  return (
    <form action={action}>
      <input name="email" disabled={pending} />
      <button disabled={pending}>{pending ? 'Saving...' : 'Save'}</button>
      {state.error && <p>{state.error}</p>}
    </form>
  )
}

Performance

PriorityTechniqueImpact
P0Route-based code splitting🔴 High
P0Image optimization (next/image)🔴 High
P1Virtualize long lists (tanstack-virtual)🟡 Medium
P1Debounce expensive operations🟡 Medium
P2React.memo on expensive components🟢 Low-Med
P2useMemo for expensive calculations🟢 Low-Med

React Compiler (React 19+): Auto-memoizes. Remove manual memo/useMemo/useCallback.

Common Traps

Rendering Traps

// ❌ Renders "0" when count is 0
{count && <Component />}

// ✅ Explicit boolean
{count > 0 && <Component />}
// ❌ Mutating state — React won't detect
array.push(item)
setArray(array)

// ✅ New reference
setArray([...array, item])
// ❌ New key every render — destroys component
<Item key={Math.random()} />

// ✅ Stable key
<Item key={item.id} />

Hooks Traps

// ❌ useEffect cannot be async
useEffect(async () => { ... }, [])

// ✅ Define async inside
useEffect(() => {
  async function load() { ... }
  load()
}, [])
// ❌ Missing cleanup — memory leak
useEffect(() => {
  const sub = subscribe()
}, [])

// ✅ Return cleanup
useEffect(() => {
  const sub = subscribe()
  return () => sub.unsubscribe()
}, [])
// ❌ Object in deps — triggers every render
useEffect(() => { ... }, [{ id: 1 }])

// ✅ Extract primitives or memoize
useEffect(() => { ... }, [id])

Data Fetching Traps

// ❌ Sequential fetches — slow
const users = await fetchUsers()
const orders = await fetchOrders()

// ✅ Parallel
const [users, orders] = await Promise.all([fetchUsers(), fetchOrders()])
// ❌ Race condition — no abort
useEffect(() => {
  fetch(url).then(setData)
}, [url])

// ✅ Abort controller
useEffect(() => {
  const controller = new AbortController()
  fetch(url, { signal: controller.signal }).then(setData)
  return () => controller.abort()
}, [url])

AI Mistakes to Avoid

Common errors AI assistants make with React:

MistakeCorrect Pattern
useEffect for derived stateCompute inline: const x = a + b
Redux for API dataTanStack Query for server state
Default exportsNamed exports: export function X
Index as key in dynamic listsStable IDs: key={item.id}
Fetching in useEffectTanStack Query or loader patterns
Giant components (500+ lines)Split at 50 lines JSX, 300 lines file
No error boundariesAdd at app, feature, component level
Ignoring TypeScript strictEnable strict: true, fix all errors

Quick Reference

Hooks

HookPurpose
useStateLocal state
useEffectSide effects (subscriptions, DOM)
useCallbackStable function reference
useMemoExpensive calculation
useRefMutable ref, DOM access
use()Read promise/context (React 19)
useActionStateForm action state (React 19)
useOptimisticOptimistic UI (React 19)

File Structure

src/
├── app/                 # Routes (Next.js)
├── features/            # Feature modules
│   └── auth/
│       ├── components/  # Feature components
│       ├── hooks/       # Feature hooks
│       ├── api/         # API calls
│       └── index.ts     # Public exports
├── shared/              # Cross-feature
│   ├── components/ui/   # Button, Input, etc.
│   └── hooks/           # useDebounce, etc.
└── providers/           # Context providers

Setup

See setup.md for first-time configuration. Uses memory-template.md for project tracking.

Core Rules

  1. Server state ≠ client state — API data goes in TanStack Query, UI state in useState/Zustand. Never mix.
  2. Named exports onlyexport function X not export default. Enables safe refactoring.
  3. Colocate, then extract — Start with state near usage. Lift only when needed.
  4. No useEffect for derived state — Compute inline: const total = items.reduce(...). Effects are for side effects.
  5. Stable keys always — Use item.id, never index for dynamic lists.
  6. Max 50 lines JSX — If bigger, extract components. Max 300 lines per file.
  7. TypeScript strict: true — No any, no implicit nulls. Catch bugs at compile time.

Related Skills

Install with clawhub install <slug> if user confirms:

  • frontend-design-ultimate — Build complete UIs with React + Tailwind
  • typescript — TypeScript patterns and strict configuration
  • nextjs — Next.js App Router and deployment
  • testing — Testing React components with Testing Library

Feedback

  • If useful: clawhub star react
  • Stay updated: clawhub sync

如何使用「React」?

  1. 打开小龙虾AI(Web 或 iOS App)
  2. 点击上方「立即使用」按钮,或在对话框中输入任务描述
  3. 小龙虾AI 会自动匹配并调用「React」技能完成任务
  4. 结果即时呈现,支持继续对话优化

相关技能