Your designer just handed you a Figma file with 30 screens, your tech lead wants TypeScript everywhere, and the deadline is next Friday. These recipes turn that pressure into shipped features. Each one is a copy-paste prompt that produces production-quality React code — not a tutorial component that falls apart when you add real data.
Prompts for generating typed React components from designs or requirements
State management recipes for Zustand, React Query, and context patterns
Performance optimization prompts that find and fix real bottlenecks
Testing recipes that produce meaningful coverage, not checkbox tests
Scenario: You have a Figma design for a pricing card and need a pixel-accurate React component with TypeScript props and Tailwind styling.
Enable Figma MCP server in your Figma desktop app (Preferences > Enable Dev Mode MCP Server), then add it in Cursor Settings > MCP. Select the component in Figma, then open Agent mode.
Add Figma MCP: claude mcp add figma --transport sse http://127.0.0.1:3845/sse. Then reference the selection in your prompt.
Configure Figma MCP in your codex.json, then reference the Figma selection in any Codex surface.
Tip
Using the Figma MCP server, generate a React component from my current Figma selection. Requirements: TypeScript with explicit prop interface, Tailwind CSS for all styling, responsive breakpoints at sm/md/lg, named export, and a Storybook story file alongside the component. Extract design tokens (colors, spacing, radii) from the Figma variables and map them to Tailwind classes.
Expected output: A .tsx component file with a typed props interface, Tailwind classes matching the design, responsive variants, and a companion .stories.tsx file with at least three variants (default, loading, error).
Scenario: You need a reusable data table component for an admin dashboard that handles 10,000+ rows without choking.
Tip
Create a generic DataTable component using @tanstack/react-table v8. Requirements: TypeScript generics so the component accepts any row type via a data prop and a columns ColumnDef array. Include click-to-sort on column headers with asc/desc/none cycling, a text filter input per column, pagination with configurable page sizes (10, 25, 50, 100), loading skeleton state, empty state with customizable message, row selection with checkbox column and a onSelectionChange callback. Style with Tailwind. Add keyboard navigation for accessibility. Write the component, the types file, and a usage example with mock user data.
Expected output: Three files — DataTable.tsx with the generic component, data-table.types.ts with shared types, and DataTableExample.tsx demonstrating usage with a User type.
Scenario: You inherited a 400-line class component with componentDidMount, componentDidUpdate, and shouldComponentUpdate. It needs to become a functional component without changing any behavior.
Tip
Refactor the class component in src/components/UserDashboard.tsx to a functional component with hooks. Map every lifecycle method: componentDidMount becomes useEffect with empty deps, componentDidUpdate becomes useEffect with specific deps, shouldComponentUpdate becomes React.memo with a custom comparison function. Extract any complex state logic into a custom useUserDashboard hook in a separate file. Preserve all existing behavior — do not change props, do not change rendered output, do not change API calls. Run existing tests after refactoring to confirm nothing broke.
Expected output: A functional UserDashboard component, a useUserDashboard.ts custom hook, and all existing tests still passing.
Scenario: You need global client state for user preferences, theme, and sidebar collapse state. It should survive page refreshes.
Tip
Create a Zustand store in src/stores/app-store.ts with full TypeScript typing. Include these slices: user (profile data, isAuthenticated boolean, login/logout actions), preferences (theme as ‘light’ | ‘dark’ | ‘system’, sidebarCollapsed boolean, locale string, toggle actions for each), notifications (items array, unreadCount derived selector, addNotification/markRead/clearAll actions). Use the persist middleware to save to localStorage with a version number for migrations. Use the devtools middleware in development. Export typed selectors like useUser(), usePreferences(), useNotifications() so consumers do not access the raw store. Write unit tests for each action.
Expected output: The store file, a selectors.ts file with typed hooks, and a __tests__/app-store.test.ts file testing all actions and persistence.
Scenario: Your app makes 15 different API calls and you are managing loading/error states with useState everywhere. Time to centralize with React Query.
Tip
Set up TanStack Query v5 in this React app. Create a src/lib/query-client.ts that configures a QueryClient with these defaults: staleTime of 5 minutes, gcTime of 30 minutes, retry 2 times with exponential backoff, refetchOnWindowFocus only in production. Then create custom hooks in src/hooks/api/: useUsers() for listing with pagination params, useUser(id) for single fetch, useCreateUser() mutation with optimistic update that adds the new user to the list cache immediately, useUpdateUser() mutation that patches the user in both list and detail caches, useDeleteUser() mutation with optimistic removal. Each hook should handle error states with typed error responses. Include a QueryProvider wrapper component. Write tests using @testing-library/react with a custom renderWithProviders utility.
Expected output: Query client config, 5 custom hooks, a provider wrapper, a test utility, and at least one test per hook.
Scenario: Your React app takes 4 seconds to render the product listing page. The React DevTools Profiler shows 200+ unnecessary re-renders.
Open the components directory, select all files, then use Agent mode with the prompt below.
Claude Code can read entire directories. Just point it at the components folder.
Codex can analyze the full repo. Use the prompt below in any surface.
Tip
Audit every component in src/components/products/ for performance issues. For each file, check: (1) components that accept object/array props without React.memo, (2) inline function definitions in JSX that cause child re-renders, (3) useEffect hooks with missing or overly broad dependency arrays, (4) expensive computations not wrapped in useMemo, (5) event handlers recreated every render that should use useCallback. For each issue found, apply the fix directly. Do not wrap everything in memo blindly — only where the profiler data justifies it. After fixes, add a comment at the top of each modified file noting what was optimized and why.
Expected output: Modified component files with targeted optimizations, each documented with a comment explaining the performance rationale.
Scenario: You have a CheckoutForm component with validation, API calls, and conditional rendering. It has zero tests.
Tip
Write tests for src/components/CheckoutForm.tsx using Vitest and @testing-library/react. Cover these scenarios: (1) renders all form fields with correct labels and placeholders, (2) shows validation errors when submitting empty required fields, (3) shows inline validation on blur for email format, credit card number length, and expiry date in the past, (4) disables submit button while form is submitting, (5) calls the onSubmit prop with sanitized form data on valid submission, (6) displays API error message when submission fails with a 422 response, (7) displays success state and calls onSuccess callback after successful submission, (8) handles network timeout gracefully with retry option. Mock the API client, not fetch directly. Use userEvent for all interactions. Test accessibility: every input has an associated label, error messages use aria-live regions.
Expected output: A CheckoutForm.test.tsx file with 8+ test cases, proper mocking setup, and accessibility assertions.
Scenario: Your team keeps reimplementing the same patterns — debouncing, local storage sync, media queries, intersection observer. You need a shared hooks library.
Tip
Create a custom hooks library in src/hooks/ with these hooks, each in its own file with TypeScript generics where applicable and a companion test file:
useDebounce<T>(value: T, delay: number) — returns debounced value, cancels on unmount
useLocalStorage<T>(key: string, initialValue: T) — syncs state to localStorage, handles SSR gracefully, listens for storage events from other tabs
useMediaQuery(query: string) — returns boolean match, uses matchMedia API, handles SSR with a fallback
useIntersectionObserver(options?) — returns ref and IntersectionObserverEntry, lazy-initializes the observer
useClickOutside<T extends HTMLElement>(handler: () => void) — returns ref to attach to the element, cleans up listener on unmount
usePrevious<T>(value: T) — returns the value from the previous render
useAsync<T>(asyncFn: () => Promise<T>) — returns { data, error, loading, execute }, with abort support
Export all hooks from src/hooks/index.ts. Each test file should cover the happy path, edge cases, and cleanup behavior.
Expected output: Seven hook files, seven test files, and a barrel export index.ts.
Scenario: When a component in your dashboard crashes, the entire page goes white. You need granular error boundaries that let users retry.
Tip
Create an error boundary system with three components: (1) ErrorBoundary — a class component (required for getDerivedStateFromError) that catches errors, logs them to your error reporting service via an onError prop, and renders a fallback UI with a “Try Again” button that resets the boundary state. Accept a fallback render prop that receives the error and a reset function. (2) SectionErrorBoundary — wraps ErrorBoundary with a styled card fallback specific to dashboard sections, showing the section name and a friendly message. (3) withErrorBoundary HOC — wraps any component in an ErrorBoundary with sensible defaults. Include TypeScript generics so the HOC preserves the wrapped component’s prop types. Add a useErrorHandler() hook that lets child components programmatically trigger the nearest error boundary for async errors that getDerivedStateFromError cannot catch. Test that the boundary catches render errors, displays the fallback, and resets when the user clicks retry.
Expected output: Three component files, one hook file, one test file covering error catching and recovery.
Scenario: You are migrating a Next.js page to use React Server Components. You need to identify which parts need "use client" and which can stay on the server.
Tip
Analyze src/app/dashboard/page.tsx and its child components. For each component, determine: does it use useState, useEffect, event handlers, browser APIs, or context? If yes, it must be a client component. If it only renders props and fetches data, keep it as a server component. Refactor the page so that: the page layout, data fetching, and static content stay as server components. Interactive elements (filters, modals, forms) become client components with “use client” at the top. Create a clear boundary — server components pass serializable props to client components. Ensure no server-only code (database queries, environment variables) leaks into client components. Add a comment at the top of each file: ”// Server Component” or ”// Client Component — uses [reason]”.
Expected output: Refactored page with clear server/client boundaries, documented with comments explaining each decision.
Scenario: Your app has 5 different modal implementations, none of them handle focus trapping or keyboard navigation correctly.
Tip
Create a unified modal system in src/components/ui/Modal/. Include: (1) Modal component that renders into a portal, traps focus inside using a focus-trap loop, closes on Escape key, closes on backdrop click (configurable), applies aria-modal=“true” and role=“dialog”, restores focus to the trigger element on close, prevents body scroll when open. (2) ModalHeader, ModalBody, ModalFooter compound components for consistent layout. (3) useModal() hook that returns { isOpen, open, close, toggle } with a stable identity for the callbacks. (4) ConfirmModal — a pre-built variant for confirm/cancel dialogs with customizable title, message, and button labels. Style with Tailwind, animate with CSS transitions (fade + scale). Test keyboard navigation (Tab cycles through focusable elements, Shift+Tab goes backward, Escape closes), screen reader attributes, and body scroll lock.
Expected output: Modal component directory with compound components, hook, confirm variant, and accessibility tests.
Scenario: Your todo list feels sluggish because every action waits for the server response before updating the UI.
Tip
Refactor the todo list in src/features/todos/ to use optimistic updates with TanStack Query. For each mutation: (1) addTodo — immediately append the new todo to the list cache with a temporary ID (use crypto.randomUUID()), show it in the UI with a subtle “syncing” indicator, replace the temp ID with the server ID on success, roll back and show an error toast on failure. (2) toggleTodo — immediately flip the completed state in cache, revert on failure. (3) deleteTodo — immediately remove from cache, restore on failure with an “undo” toast that persists for 5 seconds. (4) reorderTodos — immediately reorder in cache using the new position, revert on failure. Use TanStack Query’s onMutate, onError, and onSettled callbacks for the optimistic logic. Write tests that verify the optimistic state appears before the API resolves.
Expected output: Refactored mutation hooks with optimistic update logic, updated UI components showing sync indicators, and tests verifying optimistic behavior.
Scenario: Your app has 12 forms and each one handles validation differently. You need a consistent form system.
Tip
Build a form system using React Hook Form v7 and Zod for validation. Create: (1) A FormField component that accepts a Zod schema field, renders the appropriate input type (text, email, number, select, textarea, checkbox, radio group, date picker), shows validation errors below the field, and supports custom render via a render prop. (2) A Form component that wraps React Hook Form’s FormProvider, accepts a Zod schema as the schema prop, infers TypeScript types from the schema for the onSubmit handler, and handles server-side validation errors by mapping them to fields. (3) Zod schemas for common patterns: loginSchema, registrationSchema, profileSchema, addressSchema. (4) A useFormWithSchema<T>(schema) hook that returns the form methods with properly inferred types. Test that validation errors display correctly, that server errors map to fields, and that the form submits only when valid.
Expected output: FormField component, Form wrapper, 4 Zod schemas, custom hook, and validation tests.
Scenario: Your bundle is 2.4 MB and the initial load takes 6 seconds on mobile. Most users only visit 2-3 pages per session.
Tip
Implement route-based code splitting for the React Router setup in src/App.tsx. For each route: (1) Convert the static import to React.lazy() with a dynamic import. (2) Wrap each lazy route in a Suspense boundary with a skeleton loader that matches the page layout (not a generic spinner). (3) Create a LazyRoute wrapper component that combines Suspense with an ErrorBoundary so that chunk load failures show a “Failed to load page. Refresh to try again.” message instead of a white screen. (4) Add route prefetching: when the user hovers over a navigation link for 200ms, start loading that route’s chunk using a dynamic import() call. (5) Create a prefetchRoute utility that can be called programmatically (e.g., after login, prefetch the dashboard route). Verify that the main bundle drops below 200KB and each route chunk loads independently.
Expected output: Updated router with lazy routes, Suspense wrappers, error boundaries, prefetch utility, and a LazyRoute component.
Scenario: Your CRA build takes 90 seconds and hot reload has a 3-second delay. Time to move to Vite.
Tip
Migrate this Create React App project to Vite. Steps: (1) Create vite.config.ts with the React plugin, resolve aliases matching the existing tsconfig paths, and environment variable handling (convert all REACT_APP_ prefixes to VITE_). (2) Move public/index.html to index.html at the root and add the Vite script entry point. (3) Update tsconfig.json to use Vite types instead of react-scripts types. (4) Replace react-scripts with vite in package.json scripts (dev, build, preview). (5) Fix any import issues: CRA supports importing SVGs as components via import { ReactComponent } — replace these with vite-plugin-svgr. (6) Update environment variable access from process.env.REACT_APP_* to import.meta.env.VITE_* across all files. (7) Remove react-scripts, react-app-rewired, and any CRA-specific dependencies. (8) Verify the dev server starts, the production build succeeds, and all tests still pass.
Expected output: Updated config files, migrated environment variables, removed CRA dependencies, and a working Vite setup.