Claude
Skills
Sign in
Back

react

Included with Lifetime
$97 forever

React component discipline: pure components, minimal state, effects as escape hatches. Invoke whenever task involves any interaction with React code — writing, reviewing, refactoring, debugging, or understanding JSX, hooks, component architecture, state management, or performance optimization.

Design

What this skill does


# React

**Components are pure functions. State is minimal. Effects are escape hatches. If you reach for useEffect, verify you
actually need it.**

React rewards thinking in components: break UI into pieces, find minimal state, identify where it lives, and wire data
flow from parent to child. References contain extended examples, rationale, and edge cases for each topic area.

## References

- **Components** — `${CLAUDE_SKILL_DIR}/references/components.md` Composition, refs, metadata, custom elements
- **Hooks** — `${CLAUDE_SKILL_DIR}/references/hooks.md` Hook rules, custom hooks, `useSyncExternalStore`
- **State** — `${CLAUDE_SKILL_DIR}/references/state.md` Placement, reducers, context, actions
- **Performance** — `${CLAUDE_SKILL_DIR}/references/performance.md` Compiler, memoization, server components, streaming
- **Testing** — `${CLAUDE_SKILL_DIR}/references/testing.md` Query priority/variants, userEvent catalog, async patterns

## Component Design

### Thinking in React

Build UI in five steps:

1. Break UI into a component hierarchy — each component does one thing.
2. Build a static version first — props only, no state, no interactivity.
3. Find minimal state — if it doesn't change, is passed from a parent, or can be computed, it is not state.
4. Identify where state lives — find every component that renders based on the state, find their closest common parent,
   put state there.
5. Add inverse data flow — pass state-setter callbacks down so children update parent state through event handlers.

### Purity

React assumes every component is a pure function. Same props + same state = same JSX. Never mutate props, state, or
variables declared before rendering.

- **Local mutation is fine.** Creating and mutating objects/arrays within the same render is safe — the mutation is
  invisible outside that render.
- **Event handlers don't need to be pure** — they run outside of rendering.

### Component Structure

- One component per file. Small helpers co-located in the same file are acceptable but extract when reused.
- Prefer function declarations for components.
- Do not use `React.FC` — it adds implicit `children` typing and complicates generics. Use
  `function Component(props: Props)`.

### Component Body Organization

Separate logic from rendering. The component body handles computation, state, and handler definitions. JSX is
declarative — it references results, not processes.

- **Handler object** — group all event handlers in a single `handle` object. This creates a clear boundary between logic
  and rendering:
  ```tsx
  const handle = {
    submit() { /* ... */ },
    inputChange(e: ChangeEvent<HTMLInputElement>) { setName(e.target.value); },
    keyDown(e: KeyboardEvent) { if (e.key === 'Enter') handle.submit(); },
  };
  ```
  Reference in JSX as `onChange={handle.inputChange}`. Never inline handler logic in JSX.
- **Pre-render computation** — move list rendering and derived JSX out of the return statement into component body
  variables:
  ```tsx
  const tabElements: ReactNode[] = [];
  for (const tab of allTabs) {
    tabElements.push(<Tab key={tab.id}>{tab.name}</Tab>);
  }
  return <TabList>{tabElements}</TabList>;
  ```
  JSX `.map()` inside the return statement is discouraged — compute element arrays in the body, reference them in JSX.
- **Conditional rendering** — simple conditions (`{isVisible && <Component />}`) are acceptable inline in JSX. When the
  condition is complex or involves multiple branches, compute the result in the component body and reference the
  variable in JSX.

### Composition

- Props flow down, events flow up. One-way data flow. Children never mutate parent state directly — they call callbacks.
- Composition over configuration. Pass JSX as `children` or render props instead of building components with dozens of
  boolean flags.
- When a wrapper component updates its own state, React knows its `children` props haven't changed, so children skip
  re-rendering.
- Use compound components (shared context between related sub-components) for complex UI patterns like flyout menus,
  tabs, accordions.
- Prefer controlled components when parent needs to coordinate state across siblings. Prefer uncontrolled for isolated,
  self-contained UI.

### Refs

- `ref` is a prop. Pass `ref` directly as a prop to function components. Never use `forwardRef` — it is deprecated.
- Ref callbacks can return a cleanup function, called when the element unmounts.
- Avoid implicit returns in ref callbacks — use block body `{}` not parentheses to prevent TypeScript confusion.

### Document Metadata

Render `<title>`, `<meta>`, `<link>` directly in components. React hoists them to `<head>` automatically. Works with
client-only apps, streaming SSR, and Server Components.

### Custom Elements

React provides full custom element support. Server rendering: primitive props render as attributes, non-primitive props
are omitted. Client rendering: props matching element instance properties are assigned as properties, others as
attributes.

## JSX Conventions

- Self-closing tags for components without children: `<Input />`.
- Boolean attributes without value: `<Input disabled />` not `disabled={true}`.
- Fragments to avoid wrapper divs: `<>...</>` or `<Fragment key={id}>`.
- Avoid `&&` with numbers — `count && <List />` renders `0`. Use `count > 0 && <List />` or a ternary.
- Never inline handler logic in JSX. Group all handlers in a `handle` object in the component body (see Component Body
  Organization).
- Spread props sparingly — `{...props}` makes it unclear what a component accepts. Prefer explicit props.
- `key` on every list item. Stable, unique identifiers. Never use array index as key when items can reorder.
- No side effects during render. Event handlers for user actions, Effects for synchronization, render for pure
  computation.

## Hooks

### `use()` — Context and Promises

- Prefer `use(MyContext)` over `useContext(MyContext)`. `use()` can be called inside conditionals and loops —
  `useContext()` cannot.
- `use()` always looks for the closest provider **above** the calling component.
- `use(promise)` integrates with Suspense and Error Boundaries to read promise values.
- Do not create promises inside Client Components during render — they recreate every render. Pass promises from Server
  Components or use a Suspense-compatible library.
- In Server Components, prefer `async`/`await` over `use()`.
- `use()` cannot be called in a try-catch block. Use Error Boundaries or `promise.catch()` instead.

### Hook Rules

- Top level only. Never call hooks inside conditions, loops, or nested functions. React relies on call order. Exception:
  `use()` can be called conditionally.
- React functions only. Call hooks from function components or custom hooks — never from regular JavaScript functions.
- Exhaustive deps. Include all reactive values used inside the Effect in the dependency array. The linter enforces this
  — don't suppress it. If a dependency causes unwanted re-runs, restructure the code.
- One Effect per concern. Don't merge unrelated sync logic into a single Effect. Separate Effects for separate external
  systems.

### Effects Are Escape Hatches

Use Effects **only** to synchronize with external systems (DOM APIs, network, browser events). Not for transforming
data, handling user events, or state derivation.

**You don't need an Effect for:**

- **Transform data for rendering** — Compute during render
- **Handle user events** — Call in event handler
- **Reset state on prop change** — Use `key={userId}` on the component
- **Adjust state on prop change** — Compute: `items.find(...)` during render
- **Notify parent of state change** — Call `onChange` in the event handler
- **Share logic between handlers** — Extract a function, call from both handlers
- **Chain state updates** — Calculate all state in one event handler

**You DO need an Effect for:**

- Subscribing to browser events (online/offline, resize, intersection)
- Connecting t
Files: 7
Size: 60.9 KB
Complexity: 50/100
Category: Design

Related in Design