React 19 performance optimization guidelines for concurrent rendering, Server Components, actions, hooks, and memoization (formerly react-19). Use this skill when writing React 19 components, using concurrent features, or optimizing re-renders. This skill does NOT cover Next.js-specific features like the App Router, next.config.js, or Next.js caching (use the nextjs-16-app-router skill). For client-side form validation with React Hook Form, use the react-hook-form skill.
Comprehensive React 19/19.2 best-practices guide for AI agents. Contains 49 rules across 9 categories, prioritized by impact from critical (concurrent rendering, server components) through to cross-cutting codebase hygiene (dedup, dead code, boundary coherence). Reflects React 19 headline changes: ref as a regular prop (forwardRef deprecated), native document metadata, resource preload APIs, useActionState, useOptimistic, use() hook, and <Context> as provider.
Rule files describe pattern shapes (not API names) and open with a "Shapes to recognize" section listing 2–4 syntactic disguises the same break can wear. Selected high-value rules (those whose disguises are most common in real codebases — form actions, ref-as-prop, derived state, context, the use() hook, useCallback/memo pairing) include an extra concrete "In disguise" incorrect/correct example pair to teach pattern detection beyond the grep-friendly cases.
references/_review-algorithm.md for the required procedure)<Context.Provider> → <Context>, useFormState → useActionState)'use client' files that don't need the client, prop-shape drift (see Category 9)When the user asks to review, refactor, modernize, or audit React code — single file or whole repo — follow references/_review-algorithm.md. Do not improvise.
Four non-negotiables from that doc:
forwardRef; an onSubmit doing the work of useActionState; a useState+useEffect shaped like derived state; a custom hook hiding the fetch dance). Grep is a trigger, never a verdict.category × file, cells ∈ {clean, N findings, n/a}). A missing category in the output is immediately visible.Single-file ad-hoc questions ("is this hook OK?") can go straight to the relevant rule. The algorithm exists for the multi-file and whole-repo cases.
| # | Category | Impact | Rules | Key Topics | |---|----------|--------|-------|------------| | 1 | Concurrent Rendering | CRITICAL | 6 | useTransition, useDeferredValue, Activity, batching, render purity | | 2 | Server Components | CRITICAL | 6 | RSC boundaries, data fetching, streaming, serializable props | | 3 | Actions & Forms | HIGH | 5 | Form actions, declarative form state, useOptimistic, server validation | | 4 | Data Fetching | HIGH | 7 | use() hook, cache(), Suspense, document metadata, resource hints | | 5 | State Management | MEDIUM-HIGH | 5 | Derived values, context split, functional updates, reducer | | 6 | Memoization & Performance | MEDIUM | 5 | React Compiler, useMemo, useCallback, React.memo | | 7 | Effects & Events | MEDIUM | 5 | useEffectEvent, cleanup, external stores, derived-state anti-pattern | | 8 | Component Patterns | LOW-MEDIUM | 5 | ref-as-prop, composition, controlled vs uncontrolled, key reset | | 9 | Codebase Hygiene | CROSS-CUTTING | 5 | Dedup, consolidation, dead code, boundary coherence, prop-shape drift |
Critical patterns — get these right first:
'use client' boundaries as low as possiblestartTransition for expensive non-blocking updates<Activity> to preserve state across tab/page switchesReact 19 modern idioms (do NOT generate React 18 patterns):
function C({ ref, ...props }) — never wrap in forwardRef<MyContext value={v}> — never use <MyContext.Provider>useActionState — never use useFormStateuseRef<T>(null) — always pass an initial value<title>, <meta>, <link> inline — never reach for react-helmetpreload/preconnect from react-dom — never hand-render <link rel="preload">Common single-file mistakes — avoid these anti-patterns:
use() (causes infinite loops)'use client' too high in the component treeCodebase-level patterns — surface these in Category 9 sweeps:
'use client' files whose hook usage doesn't require client execution — demote to Server Components (or split into server parent + client island)<Activity>)useDeferredValue)useTransition)useEffect+fetch in a Client Component — CRITICAL'use client' boundary down to the interactive leaf, not up at the route — CRITICALchildren or named slots, not by being imported — HIGHaction prop, not a JS-only onSubmit handler — HIGHuseActionState)useFormStatus)useOptimistic)await is a waterfall — MEDIUM-HIGHcache())if (loading) return … — HIGHuse() instead of useEffect+useState plumbing — HIGH (use())<title>/<meta>/<link> inline — drop helmet-style head managers — MEDIUMreact-dom instead of hand-rendering <link rel="preload"> — MEDIUMsetX(prev => …) — not setX(x + 1) — MEDIUM-HIGHuseState when the initial value is expensive — never compute it inline — MEDIUM-HIGHuseState cells — MEDIUM (useReducer)useMemo/useCallback noise — MEDIUMmemo() only when their props are actually stable — MEDIUMuseCallback)useMemo)useEffect is for syncing with external systems — never for derived state, mutations, event logic, parent notification, or app init — HIGHuseEffectEvent)useSyncExternalStore, not useEffect + useState — MEDIUMref as a normal destructured prop — drop the forwardRef wrapper, drop the drilling — MEDIUM-HIGH<form action> — LOW-MEDIUMchildren instead and let callers compose — LOW-MEDIUMkey={entity.id} — let React tear down stale state for you — LOW-MEDIUMnextjs-16-app-router skillreact-hook-form skilltanstack-query skillSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer