{
  "schemaVersion": "1.0",
  "item": {
    "slug": "react",
    "name": "React",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/ivangdavila/react",
    "canonicalUrl": "https://clawhub.ai/ivangdavila/react",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/react",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=react",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "memory-template.md",
      "setup.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/react"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/react",
    "agentPageUrl": "https://openagent3.xyz/skills/react/agent",
    "manifestUrl": "https://openagent3.xyz/skills/react/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/react/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "React",
        "body": "Production-grade React engineering. This skill transforms how you build React applications — from component architecture to deployment."
      },
      {
        "title": "When to Use",
        "body": "Building React components, pages, or features\nImplementing state management (useState, Context, Zustand, TanStack Query)\nWorking with React 19 (Server Components, use(), Actions)\nOptimizing performance (memo, lazy, Suspense)\nDebugging rendering issues, infinite loops, stale closures\nSetting up project architecture and folder structure"
      },
      {
        "title": "Architecture Decisions",
        "body": "Before writing code, make these decisions:\n\nDecisionOptionsDefaultRenderingSPA / SSR / Static / HybridSSR (Next.js)State (server)TanStack Query / SWR / use()TanStack QueryState (client)useState / Zustand / JotaiZustand if sharedStylingTailwind / CSS Modules / styledTailwindFormsReact Hook Form + Zod / nativeRHF + Zod\n\nRule: Server state (API data) and client state (UI state) are DIFFERENT. Never mix them."
      },
      {
        "title": "Component Rules",
        "body": "// ✅ The correct pattern\nexport function UserCard({ user, onEdit }: UserCardProps) {\n  // 1. Hooks first (always)\n  const [isOpen, setIsOpen] = useState(false)\n  \n  // 2. Derived state (NO useEffect for this)\n  const fullName = `${user.firstName} ${user.lastName}`\n  \n  // 3. Handlers\n  const handleEdit = useCallback(() => onEdit(user.id), [onEdit, user.id])\n  \n  // 4. Early returns\n  if (!user) return null\n  \n  // 5. JSX (max 50 lines)\n  return (...)\n}\n\nRuleWhyNamed exports onlyRefactoring safety, IDE supportProps interface exportedReusable, documentedMax 50 lines JSXExtract if biggerMax 300 lines fileSplit into componentsHooks at topReact rules + predictable"
      },
      {
        "title": "State Management",
        "body": "Is it from an API?\n├─ YES → TanStack Query (NOT Redux, NOT Zustand)\n└─ NO → Is it shared across components?\n    ├─ YES → Zustand (simple) or Context (if rarely changes)\n    └─ NO → useState"
      },
      {
        "title": "TanStack Query (Server State)",
        "body": "// Query key factory — prevents key typos\nexport const userKeys = {\n  all: ['users'] as const,\n  detail: (id: string) => [...userKeys.all, id] as const,\n}\n\nexport function useUser(id: string) {\n  return useQuery({\n    queryKey: userKeys.detail(id),\n    queryFn: () => fetchUser(id),\n    staleTime: 5 * 60 * 1000, // 5 min\n  })\n}"
      },
      {
        "title": "Zustand (Client State)",
        "body": "// Thin stores, one concern each\nexport const useUIStore = create<UIState>()((set) => ({\n  sidebarOpen: true,\n  toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),\n}))\n\n// ALWAYS use selectors — prevents unnecessary rerenders\nconst isOpen = useUIStore((s) => s.sidebarOpen)"
      },
      {
        "title": "Server Components (Default in Next.js App Router)",
        "body": "// Server Component — runs on server, zero JS to client\nasync function ProductList() {\n  const products = await db.products.findMany() // Direct DB access\n  return <ul>{products.map(p => <ProductCard key={p.id} product={p} />)}</ul>\n}\n\n// Client Component — needs 'use client' directive\n'use client'\nfunction AddToCartButton({ productId }: { productId: string }) {\n  const [loading, setLoading] = useState(false)\n  return <button onClick={() => addToCart(productId)}>Add</button>\n}\n\nServer ComponentClient Componentasync/await ✅useState ✅Direct DB ✅onClick ✅No bundle sizeAdds to bundleuseState ❌async ❌"
      },
      {
        "title": "use() Hook",
        "body": "// Read promises in render (with Suspense)\nfunction Comments({ promise }: { promise: Promise<Comment[]> }) {\n  const comments = use(promise) // Suspends until resolved\n  return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>\n}"
      },
      {
        "title": "useActionState (Forms)",
        "body": "'use client'\nasync function submitAction(prev: State, formData: FormData) {\n  'use server'\n  // ... server logic\n  return { success: true }\n}\n\nfunction Form() {\n  const [state, action, pending] = useActionState(submitAction, {})\n  return (\n    <form action={action}>\n      <input name=\"email\" disabled={pending} />\n      <button disabled={pending}>{pending ? 'Saving...' : 'Save'}</button>\n      {state.error && <p>{state.error}</p>}\n    </form>\n  )\n}"
      },
      {
        "title": "Performance",
        "body": "PriorityTechniqueImpactP0Route-based code splitting🔴 HighP0Image optimization (next/image)🔴 HighP1Virtualize long lists (tanstack-virtual)🟡 MediumP1Debounce expensive operations🟡 MediumP2React.memo on expensive components🟢 Low-MedP2useMemo for expensive calculations🟢 Low-Med\n\nReact Compiler (React 19+): Auto-memoizes. Remove manual memo/useMemo/useCallback."
      },
      {
        "title": "Rendering Traps",
        "body": "// ❌ Renders \"0\" when count is 0\n{count && <Component />}\n\n// ✅ Explicit boolean\n{count > 0 && <Component />}\n\n// ❌ Mutating state — React won't detect\narray.push(item)\nsetArray(array)\n\n// ✅ New reference\nsetArray([...array, item])\n\n// ❌ New key every render — destroys component\n<Item key={Math.random()} />\n\n// ✅ Stable key\n<Item key={item.id} />"
      },
      {
        "title": "Hooks Traps",
        "body": "// ❌ useEffect cannot be async\nuseEffect(async () => { ... }, [])\n\n// ✅ Define async inside\nuseEffect(() => {\n  async function load() { ... }\n  load()\n}, [])\n\n// ❌ Missing cleanup — memory leak\nuseEffect(() => {\n  const sub = subscribe()\n}, [])\n\n// ✅ Return cleanup\nuseEffect(() => {\n  const sub = subscribe()\n  return () => sub.unsubscribe()\n}, [])\n\n// ❌ Object in deps — triggers every render\nuseEffect(() => { ... }, [{ id: 1 }])\n\n// ✅ Extract primitives or memoize\nuseEffect(() => { ... }, [id])"
      },
      {
        "title": "Data Fetching Traps",
        "body": "// ❌ Sequential fetches — slow\nconst users = await fetchUsers()\nconst orders = await fetchOrders()\n\n// ✅ Parallel\nconst [users, orders] = await Promise.all([fetchUsers(), fetchOrders()])\n\n// ❌ Race condition — no abort\nuseEffect(() => {\n  fetch(url).then(setData)\n}, [url])\n\n// ✅ Abort controller\nuseEffect(() => {\n  const controller = new AbortController()\n  fetch(url, { signal: controller.signal }).then(setData)\n  return () => controller.abort()\n}, [url])"
      },
      {
        "title": "AI Mistakes to Avoid",
        "body": "Common errors AI assistants make with React:\n\nMistakeCorrect PatternuseEffect for derived stateCompute inline: const x = a + bRedux for API dataTanStack Query for server stateDefault exportsNamed exports: export function XIndex as key in dynamic listsStable IDs: key={item.id}Fetching in useEffectTanStack Query or loader patternsGiant components (500+ lines)Split at 50 lines JSX, 300 lines fileNo error boundariesAdd at app, feature, component levelIgnoring TypeScript strictEnable strict: true, fix all errors"
      },
      {
        "title": "Hooks",
        "body": "HookPurposeuseStateLocal stateuseEffectSide effects (subscriptions, DOM)useCallbackStable function referenceuseMemoExpensive calculationuseRefMutable ref, DOM accessuse()Read promise/context (React 19)useActionStateForm action state (React 19)useOptimisticOptimistic UI (React 19)"
      },
      {
        "title": "File Structure",
        "body": "src/\n├── app/                 # Routes (Next.js)\n├── features/            # Feature modules\n│   └── auth/\n│       ├── components/  # Feature components\n│       ├── hooks/       # Feature hooks\n│       ├── api/         # API calls\n│       └── index.ts     # Public exports\n├── shared/              # Cross-feature\n│   ├── components/ui/   # Button, Input, etc.\n│   └── hooks/           # useDebounce, etc.\n└── providers/           # Context providers"
      },
      {
        "title": "Setup",
        "body": "See setup.md for first-time configuration. Uses memory-template.md for project tracking."
      },
      {
        "title": "Core Rules",
        "body": "Server state ≠ client state — API data goes in TanStack Query, UI state in useState/Zustand. Never mix.\nNamed exports only — export function X not export default. Enables safe refactoring.\nColocate, then extract — Start with state near usage. Lift only when needed.\nNo useEffect for derived state — Compute inline: const total = items.reduce(...). Effects are for side effects.\nStable keys always — Use item.id, never index for dynamic lists.\nMax 50 lines JSX — If bigger, extract components. Max 300 lines per file.\nTypeScript strict: true — No any, no implicit nulls. Catch bugs at compile time."
      },
      {
        "title": "Related Skills",
        "body": "Install with clawhub install <slug> if user confirms:\n\nfrontend-design-ultimate — Build complete UIs with React + Tailwind\ntypescript — TypeScript patterns and strict configuration\nnextjs — Next.js App Router and deployment\ntesting — Testing React components with Testing Library"
      },
      {
        "title": "Feedback",
        "body": "If useful: clawhub star react\nStay updated: clawhub sync"
      }
    ],
    "body": "React\n\nProduction-grade React engineering. This skill transforms how you build React applications — from component architecture to deployment.\n\nWhen to Use\nBuilding React components, pages, or features\nImplementing state management (useState, Context, Zustand, TanStack Query)\nWorking with React 19 (Server Components, use(), Actions)\nOptimizing performance (memo, lazy, Suspense)\nDebugging rendering issues, infinite loops, stale closures\nSetting up project architecture and folder structure\nArchitecture Decisions\n\nBefore writing code, make these decisions:\n\nDecision\tOptions\tDefault\nRendering\tSPA / SSR / Static / Hybrid\tSSR (Next.js)\nState (server)\tTanStack Query / SWR / use()\tTanStack Query\nState (client)\tuseState / Zustand / Jotai\tZustand if shared\nStyling\tTailwind / CSS Modules / styled\tTailwind\nForms\tReact Hook Form + Zod / native\tRHF + Zod\n\nRule: Server state (API data) and client state (UI state) are DIFFERENT. Never mix them.\n\nComponent Rules\n// ✅ The correct pattern\nexport function UserCard({ user, onEdit }: UserCardProps) {\n  // 1. Hooks first (always)\n  const [isOpen, setIsOpen] = useState(false)\n  \n  // 2. Derived state (NO useEffect for this)\n  const fullName = `${user.firstName} ${user.lastName}`\n  \n  // 3. Handlers\n  const handleEdit = useCallback(() => onEdit(user.id), [onEdit, user.id])\n  \n  // 4. Early returns\n  if (!user) return null\n  \n  // 5. JSX (max 50 lines)\n  return (...)\n}\n\nRule\tWhy\nNamed exports only\tRefactoring safety, IDE support\nProps interface exported\tReusable, documented\nMax 50 lines JSX\tExtract if bigger\nMax 300 lines file\tSplit into components\nHooks at top\tReact rules + predictable\nState Management\nIs it from an API?\n├─ YES → TanStack Query (NOT Redux, NOT Zustand)\n└─ NO → Is it shared across components?\n    ├─ YES → Zustand (simple) or Context (if rarely changes)\n    └─ NO → useState\n\nTanStack Query (Server State)\n// Query key factory — prevents key typos\nexport const userKeys = {\n  all: ['users'] as const,\n  detail: (id: string) => [...userKeys.all, id] as const,\n}\n\nexport function useUser(id: string) {\n  return useQuery({\n    queryKey: userKeys.detail(id),\n    queryFn: () => fetchUser(id),\n    staleTime: 5 * 60 * 1000, // 5 min\n  })\n}\n\nZustand (Client State)\n// Thin stores, one concern each\nexport const useUIStore = create<UIState>()((set) => ({\n  sidebarOpen: true,\n  toggleSidebar: () => set((s) => ({ sidebarOpen: !s.sidebarOpen })),\n}))\n\n// ALWAYS use selectors — prevents unnecessary rerenders\nconst isOpen = useUIStore((s) => s.sidebarOpen)\n\nReact 19\nServer Components (Default in Next.js App Router)\n// Server Component — runs on server, zero JS to client\nasync function ProductList() {\n  const products = await db.products.findMany() // Direct DB access\n  return <ul>{products.map(p => <ProductCard key={p.id} product={p} />)}</ul>\n}\n\n// Client Component — needs 'use client' directive\n'use client'\nfunction AddToCartButton({ productId }: { productId: string }) {\n  const [loading, setLoading] = useState(false)\n  return <button onClick={() => addToCart(productId)}>Add</button>\n}\n\nServer Component\tClient Component\nasync/await ✅\tuseState ✅\nDirect DB ✅\tonClick ✅\nNo bundle size\tAdds to bundle\nuseState ❌\tasync ❌\nuse() Hook\n// Read promises in render (with Suspense)\nfunction Comments({ promise }: { promise: Promise<Comment[]> }) {\n  const comments = use(promise) // Suspends until resolved\n  return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>\n}\n\nuseActionState (Forms)\n'use client'\nasync function submitAction(prev: State, formData: FormData) {\n  'use server'\n  // ... server logic\n  return { success: true }\n}\n\nfunction Form() {\n  const [state, action, pending] = useActionState(submitAction, {})\n  return (\n    <form action={action}>\n      <input name=\"email\" disabled={pending} />\n      <button disabled={pending}>{pending ? 'Saving...' : 'Save'}</button>\n      {state.error && <p>{state.error}</p>}\n    </form>\n  )\n}\n\nPerformance\nPriority\tTechnique\tImpact\nP0\tRoute-based code splitting\t🔴 High\nP0\tImage optimization (next/image)\t🔴 High\nP1\tVirtualize long lists (tanstack-virtual)\t🟡 Medium\nP1\tDebounce expensive operations\t🟡 Medium\nP2\tReact.memo on expensive components\t🟢 Low-Med\nP2\tuseMemo for expensive calculations\t🟢 Low-Med\n\nReact Compiler (React 19+): Auto-memoizes. Remove manual memo/useMemo/useCallback.\n\nCommon Traps\nRendering Traps\n// ❌ Renders \"0\" when count is 0\n{count && <Component />}\n\n// ✅ Explicit boolean\n{count > 0 && <Component />}\n\n// ❌ Mutating state — React won't detect\narray.push(item)\nsetArray(array)\n\n// ✅ New reference\nsetArray([...array, item])\n\n// ❌ New key every render — destroys component\n<Item key={Math.random()} />\n\n// ✅ Stable key\n<Item key={item.id} />\n\nHooks Traps\n// ❌ useEffect cannot be async\nuseEffect(async () => { ... }, [])\n\n// ✅ Define async inside\nuseEffect(() => {\n  async function load() { ... }\n  load()\n}, [])\n\n// ❌ Missing cleanup — memory leak\nuseEffect(() => {\n  const sub = subscribe()\n}, [])\n\n// ✅ Return cleanup\nuseEffect(() => {\n  const sub = subscribe()\n  return () => sub.unsubscribe()\n}, [])\n\n// ❌ Object in deps — triggers every render\nuseEffect(() => { ... }, [{ id: 1 }])\n\n// ✅ Extract primitives or memoize\nuseEffect(() => { ... }, [id])\n\nData Fetching Traps\n// ❌ Sequential fetches — slow\nconst users = await fetchUsers()\nconst orders = await fetchOrders()\n\n// ✅ Parallel\nconst [users, orders] = await Promise.all([fetchUsers(), fetchOrders()])\n\n// ❌ Race condition — no abort\nuseEffect(() => {\n  fetch(url).then(setData)\n}, [url])\n\n// ✅ Abort controller\nuseEffect(() => {\n  const controller = new AbortController()\n  fetch(url, { signal: controller.signal }).then(setData)\n  return () => controller.abort()\n}, [url])\n\nAI Mistakes to Avoid\n\nCommon errors AI assistants make with React:\n\nMistake\tCorrect Pattern\nuseEffect for derived state\tCompute inline: const x = a + b\nRedux for API data\tTanStack Query for server state\nDefault exports\tNamed exports: export function X\nIndex as key in dynamic lists\tStable IDs: key={item.id}\nFetching in useEffect\tTanStack Query or loader patterns\nGiant components (500+ lines)\tSplit at 50 lines JSX, 300 lines file\nNo error boundaries\tAdd at app, feature, component level\nIgnoring TypeScript strict\tEnable strict: true, fix all errors\nQuick Reference\nHooks\nHook\tPurpose\nuseState\tLocal state\nuseEffect\tSide effects (subscriptions, DOM)\nuseCallback\tStable function reference\nuseMemo\tExpensive calculation\nuseRef\tMutable ref, DOM access\nuse()\tRead promise/context (React 19)\nuseActionState\tForm action state (React 19)\nuseOptimistic\tOptimistic UI (React 19)\nFile Structure\nsrc/\n├── app/                 # Routes (Next.js)\n├── features/            # Feature modules\n│   └── auth/\n│       ├── components/  # Feature components\n│       ├── hooks/       # Feature hooks\n│       ├── api/         # API calls\n│       └── index.ts     # Public exports\n├── shared/              # Cross-feature\n│   ├── components/ui/   # Button, Input, etc.\n│   └── hooks/           # useDebounce, etc.\n└── providers/           # Context providers\n\nSetup\n\nSee setup.md for first-time configuration. Uses memory-template.md for project tracking.\n\nCore Rules\nServer state ≠ client state — API data goes in TanStack Query, UI state in useState/Zustand. Never mix.\nNamed exports only — export function X not export default. Enables safe refactoring.\nColocate, then extract — Start with state near usage. Lift only when needed.\nNo useEffect for derived state — Compute inline: const total = items.reduce(...). Effects are for side effects.\nStable keys always — Use item.id, never index for dynamic lists.\nMax 50 lines JSX — If bigger, extract components. Max 300 lines per file.\nTypeScript strict: true — No any, no implicit nulls. Catch bugs at compile time.\nRelated Skills\n\nInstall with clawhub install <slug> if user confirms:\n\nfrontend-design-ultimate — Build complete UIs with React + Tailwind\ntypescript — TypeScript patterns and strict configuration\nnextjs — Next.js App Router and deployment\ntesting — Testing React components with Testing Library\nFeedback\nIf useful: clawhub star react\nStay updated: clawhub sync"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/ivangdavila/react",
    "publisherUrl": "https://clawhub.ai/ivangdavila/react",
    "owner": "ivangdavila",
    "version": "1.0.4",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/react",
    "downloadUrl": "https://openagent3.xyz/downloads/react",
    "agentUrl": "https://openagent3.xyz/skills/react/agent",
    "manifestUrl": "https://openagent3.xyz/skills/react/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/react/agent.md"
  }
}