🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

React

by @ivangdavila

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

Versionv1.0.4
Downloads6,776
Installs62
Stars⭐ 3
TERMINAL
clawhub install react

πŸ“– About This Skill


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:

    | Decision | Options | Default | |----------|---------|---------| | Rendering | SPA / SSR / Static / Hybrid | SSR (Next.js) | | State (server) | TanStack Query / SWR / use() | TanStack Query | | State (client) | useState / Zustand / Jotai | Zustand if shared | | Styling | Tailwind / CSS Modules / styled | Tailwind | | Forms | React Hook Form + Zod / native | RHF + 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 (...)
    }
    

    | Rule | Why | |------|-----| | Named exports only | Refactoring safety, IDE support | | Props interface exported | Reusable, documented | | Max 50 lines JSX | Extract if bigger | | Max 300 lines file | Split into components | | Hooks at top | React 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()((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 
      {products.map(p => )}
    }

    // Client Component β€” needs 'use client' directive 'use client' function AddToCartButton({ productId }: { productId: string }) { const [loading, setLoading] = useState(false) return }

    | Server Component | Client Component | |------------------|------------------| | async/await βœ… | useState βœ… | | Direct DB βœ… | onClick βœ… | | No bundle size | Adds to bundle | | useState ❌ | async ❌ |

    use() Hook

    // Read promises in render (with Suspense)
    function Comments({ promise }: { promise: Promise }) {
      const comments = use(promise) // Suspends until resolved
      return 
      {comments.map(c =>
    • {c.text}
    • )}
    }

    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 (

    {state.error &&

    {state.error}

    }
    ) }

    Performance

    | Priority | Technique | Impact | |----------|-----------|--------| | P0 | Route-based code splitting | πŸ”΄ High | | P0 | Image optimization (next/image) | πŸ”΄ High | | P1 | Virtualize long lists (tanstack-virtual) | 🟑 Medium | | P1 | Debounce expensive operations | 🟑 Medium | | P2 | React.memo on expensive components | 🟒 Low-Med | | P2 | useMemo 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 && }

    // βœ… Explicit boolean {count > 0 && }

    // ❌ Mutating state β€” React won't detect
    array.push(item)
    setArray(array)

    // βœ… New reference setArray([...array, item])

    // ❌ New key every render β€” destroys component
    

    // βœ… Stable key

    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:

    | Mistake | Correct Pattern | |---------|-----------------| | useEffect for derived state | Compute inline: const x = a + b | | Redux for API data | TanStack Query for server state | | Default exports | Named exports: export function X | | Index as key in dynamic lists | Stable IDs: key={item.id} | | Fetching in useEffect | TanStack Query or loader patterns | | Giant components (500+ lines) | Split at 50 lines JSX, 300 lines file | | No error boundaries | Add at app, feature, component level | | Ignoring TypeScript strict | Enable strict: true, fix all errors |

    Quick Reference

    Hooks

    | Hook | Purpose | |------|---------| | useState | Local state | | useEffect | Side effects (subscriptions, DOM) | | useCallback | Stable function reference | | useMemo | Expensive calculation | | useRef | Mutable ref, DOM access | | use() | Read promise/context (React 19) | | useActionState | Form action state (React 19) | | useOptimistic | Optimistic 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 only β€” export 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 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
  • ⚑ When to Use

    TriggerAction
    - 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

    βš™οΈ Configuration

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