← headroom.walls.sh

Claude Code for React

Claude Code is strong on React work: component generation, hook extraction, state refactors, and test loops. It reads your existing components first and matches whatever conventions are already in the codebase — no new patterns imposed on top of yours.

CLAUDE.md for a React project

Set this once so every session starts with the right context:

# React App

## Stack
- React 18 + TypeScript + Vite
- State: Zustand (global), useState/useReducer (local)
- Data fetching: TanStack Query
- Styling: Tailwind CSS
- Testing: Vitest + React Testing Library + Playwright

## Commands
- Dev: npm run dev
- Test: npm test
- E2E: npx playwright test
- Typecheck: npx tsc --noEmit
- Lint: npm run lint

## Conventions
- Components in src/components/ — PascalCase filenames
- Custom hooks in src/hooks/ — useXxx.ts
- No prop drilling past two levels — use Zustand store or context
- All new components must have TypeScript prop types
- Tests co-located: ComponentName.test.tsx next to ComponentName.tsx

Generate a component from a description

claude "create a SearchableDropdown component: takes options (label/value pairs), a placeholder string, and an onChange callback. Filterable by typing. Keyboard navigable (arrow keys + Enter). Follow the existing component patterns in src/components/."

Claude Code reads your existing components before writing anything — it matches your prop type style, event handler naming, and className conventions. The result drops in without a style clash.

Extract a custom hook

claude "the UserProfile component has fetch logic, loading state, and error state mixed into the render. Extract a useUserProfile hook that handles all of that. The component should just call the hook and render the result."

Hook extraction is one of Claude Code's strongest React tasks — it can trace data flow through a component and produce a clean separation without breaking the behavior. Add npm test -- UserProfile to the prompt and it will run the test suite after to verify nothing broke.

Fix prop drilling

claude "theme (dark/light) is drilled through 4 levels: App → Layout → Sidebar → NavItem. Replace it with a ThemeContext. Read all four files first, then make the change consistently — same context shape in all consumers."

The "read all files first" instruction matters here — prop drilling spans multiple files, and Claude Code should see all of them before editing any one of them.

Migrate a class component to a function component

claude "migrate src/components/DataTable.tsx from a class component to a function component with hooks. Preserve all props, all behavior, and all event handlers. Run the tests after."

State → useState, lifecycle methods → useEffect, refs → useRef. Claude Code handles these mappings reliably. Give it the test command so it verifies the migration.

Add TypeScript to an existing React component

claude "add TypeScript types to all props and state in src/components/Modal.jsx. Convert to .tsx. Use the existing prop shapes as the source of truth — don't change any runtime behavior, just add types."

For a larger JS→TS migration across the whole component tree:

claude "convert all .jsx files in src/components/ to TypeScript. Do them leaf-first (components with no children first, then parents). Run tsc --noEmit after each file. Stop and report if a type error in one file implies a design issue rather than a simple annotation gap."

Write component tests

claude "write Vitest + React Testing Library tests for SearchableDropdown. Cover: renders with placeholder, filters options on input, selects option on click, keyboard navigation (ArrowDown/ArrowUp/Enter), calls onChange with the right value, empty state when no matches."
claude "write tests and fix any failures. Run: npm test -- SearchableDropdown"

The two-step pattern (write tests, then run-and-fix) works better than asking for working tests upfront — it lets Claude Code see the actual failure messages and fix them precisely.

State management refactor

claude "the cart state is managed with prop drilling and local useState scattered across 6 components. Consolidate into a Zustand cartStore: items, addItem, removeItem, clearCart, total (derived). Migrate all 6 components to use the store. Run the tests after each component."

Name the store and its actions upfront — Claude Code will create a consistent interface across all consumers rather than inventing slightly different shapes in each file.

Performance: memo and callback

claude "ProfileCard re-renders on every parent update even when its props haven't changed. Identify the cause and fix it — React.memo, useMemo, or useCallback as appropriate. Explain why you chose the approach."

Ask for the explanation — Claude Code will read the render tree and give you a diagnosis, not just wrap everything in memo blindly.

Playwright end-to-end tests

claude "write a Playwright test for the checkout flow: add item to cart, open cart, enter shipping address, submit, verify confirmation page. Use the page object pattern. Run the tests after writing them."

Playwright tests are a good fit for Claude Code because the assertions are explicit and the failure output is detailed — when a test fails, Claude Code sees the error, edits the selector or assertion, and reruns until green.

React Query patterns

claude "replace the fetch+useEffect+useState pattern in src/hooks/useProducts.ts with a TanStack Query useQuery call. Add loading/error/stale states. Set staleTime to 5 minutes. Add an invalidation trigger for when a product is updated."
claude "add an optimistic update to the addToCart mutation — update the cart in the query cache immediately, roll back on error."

Monitor session budget during component work

React test loops (Vitest re-running on each edit) and large component migrations can move fast through your session budget. A migration of 20 components with test runs after each one can consume 30–40% of the 5-hour window.

Headroom — track your session budget while React tests run

When Claude Code is iterating on component tests or migrating a component tree, your 5-hour session meter is moving. Headroom shows your Claude Code session (5h) and weekly (7d) utilization live in the macOS menu bar — color-coded from calm to amber to red. No token, no API key: it reads the file Claude Code writes to ~/.claude/.

Install in one line:

brew install patwalls/tap/headroom

Start a React migration, check the menu bar. You'll know when to save a stopping point before the session limit hits mid-refactor.

Common React + Claude Code patterns

TaskPrompt pattern
New componentcreate a [Name] component: [spec]. Follow patterns in src/components/
Hook extractionextract a use[Name] hook from [Component]. Component should just call the hook.
Add testswrite RTL tests for [Component]. Cover: [cases]. Run: npm test -- [Component]
TS migrationadd TypeScript types to [Component].jsx, convert to .tsx. Run tsc --noEmit after.
Perf fixidentify why [Component] re-renders unnecessarily and fix it. Explain the cause.

Claude Code for TypeScript
Claude Code + Next.js
Writing tests with Claude Code
Claude Code multi-file editing