1---2name: react-guide3description: Use when building or editing React 19+ components, hooks, or app routing. Triggers on `.tsx`/`.jsx` files with React imports, Vite/Next configs, Server Components, `'use client'` / `'use server'` directives, and on prompts about Form Actions, useActionState, useOptimistic, use(), Suspense streaming, ref-as-prop, or the React Compiler, even when the user doesn't say 'React'.4---56# React Coding Guidelines78## Requirements910- React ≥ 19, Vite ≥ 6, Tailwind ≥ 4, Headless UI.1112## React 19 Essentials1314- **Server-first** - Components run on server by default; add `'use client'` only for interactivity15- **Form Actions** - Use `useActionState` and `FormData` instead of controlled inputs16- **Native metadata** - Use `<title>`, `<meta>`, `<link>` anywhere, auto-hoisted to `<head>`1718## Quick Reference1920| Feature | React 18 | React 19+ |21| ------------------- | --------------------------------- | --------------------------------- |22| Memoization | Manual (`useMemo`, `useCallback`) | React Compiler (automatic) |23| Forward refs | `forwardRef()` wrapper | `ref` as regular prop |24| Context provider | `<Context.Provider value={}>` | `<Context value={}>` |25| Form state | Custom `useState` | `useActionState` hook |26| Optimistic updates | Manual state | `useOptimistic` hook |27| Read promises | Not possible | `use()` hook |28| Conditional context | Not possible | `use(Context)` after conditionals |29| Form pending | Manual tracking | `useFormStatus` hook |3031## Example3233```tsx34// React 19 Form with Actions35"use client";3637import {useActionState} from "react";3839function ContactForm() {40 const [state, formAction, isPending] = useActionState(41 async (prev, formData) => {42 const result = await submitForm(Object.fromEntries(formData));43 if (result.error) return {error: result.error};44 return {success: true};45 },46 null,47 );4849 return (50 <form action={formAction}>51 <input name="email" type="email" disabled={isPending} />52 <button disabled={isPending}>53 {isPending ? "Submitting..." : "Submit"}54 </button>55 {state?.error && <p className="error">{state.error}</p>}56 </form>57 );58}5960// ref as prop (no forwardRef needed)61function Input({ref, ...props}: {ref?: React.Ref<HTMLInputElement>}) {62 return <input ref={ref} {...props} />;63}6465// Context as provider66const ThemeContext = createContext("light");6768function App({children}) {69 return <ThemeContext value="dark">{children}</ThemeContext>;70}71```7273## Essentials7475- **Component design** - Small, composable; lift/minimize state; derive when possible, see [references/component-design.md](references/component-design.md)76- **Performance** - `memo()`, `lazy()` code-splitting, Server Components for FCP/SEO, see [references/performance-optimization.md](references/performance-optimization.md)77- **Rendering** - Prefer Server Components; use Suspense for streaming, see [references/suspense-streaming.md](references/suspense-streaming.md)78- **Accessibility** - Semantic HTML, ARIA, keyboard/focus management, see [references/accessibility.md](references/accessibility.md)79- **Custom hooks** - Extract reusable logic, see [references/hooks.md](references/hooks.md)8081## Gotchas8283- Stale closures in `useEffect`: captured state from the render that scheduled the effect, not the current state; use refs or include in deps84- List keys must be stable AND unique: index keys cause re-mounts on reorder, generated keys cause re-mounts every render85- `useMemo`/`useCallback` aren't free. The comparison + bookkeeping costs more than re-running cheap computations86- Controlled vs uncontrolled inputs: passing `value` without `onChange` warns; switching mid-lifetime is silently buggy87- Server Components can't use state/effects/event handlers. The boundary is `'use client'`; mis-marking causes runtime errors only8889## Progressive Disclosure9091### Guidelines9293- Read [references/component-design.md](references/component-design.md) - Load when breaking down large components or managing state lifting94- Read [references/state-management.md](references/state-management.md) - Load when choosing between useState, useReducer, or Context95- Read [references/performance-optimization.md](references/performance-optimization.md) - Load when components re-render unnecessarily or performance lags96- Read [references/hooks.md](references/hooks.md) - Load when extracting reusable logic or creating custom hooks97- Read [references/accessibility.md](references/accessibility.md) - Load when adding keyboard navigation or screen reader support98- Read [references/new-hooks.md](references/new-hooks.md) - Load when using useActionState, useOptimistic, use(), or useFormStatus99- Read [references/server-components.md](references/server-components.md) - Load when building with RSC, Server Actions, or 'use server'/'use client' directives100- Read [references/suspense-streaming.md](references/suspense-streaming.md) - Load when using Suspense boundaries, streaming, or error handling101- Read [references/react-compiler.md](references/react-compiler.md) - Load when setting up or configuring the React Compiler102- Read [references/activity-effect-event.md](references/activity-effect-event.md) - Load when using Activity component or useEffectEvent103104### Migration from React 18105106- Read [references/migration-anti-patterns.md](references/migration-anti-patterns.md) - Load when adapting the React 18→19 mental model or avoiding outdated patterns (useEffect for data, manual loading states)107- Read [references/migration-deprecations.md](references/migration-deprecations.md) - Load when migrating from React 18 or handling removed APIs108- Read [references/migration-typescript.md](references/migration-typescript.md) - Load when fixing TypeScript errors after React 19 upgrade