We've spent six years shipping React into production — dashboards used by 40 support agents at once, editors saving every 2 seconds, tables scrolling 50k rows without dropping a frame. This page is what we've learned to keep that from turning into a maintenance disaster.
Every state bug we've ever debugged is because someone put a piece of state in the wrong territory. Get this right and your whole app calms down.
The rows in Postgres. Owned by the server. Cached and revalidated by TanStack Query. Never — never — copied into useState.
Filters, tabs, pagination, the item you have open. Lives in the URL so refresh, back, and share links all keep working.
Draft values before submit. Local to the form. React Hook Form + Zod resolver. Never global.
Is this dropdown open, which row is hovered, is the sidebar collapsed. useState in the component that owns it. That's it.
A single value in a giant context re-renders every consumer on every change. Split contexts by write frequency, or use a store (Zustand) and select what you need.
`<Row onClick={() => …}/>` creates a new function every render. Memoized children re-render anyway. Hoist the handler or pass ids and look up in the handler.
`key={index}` is not a key — it's a lie. Reordering, deleting, and animating all break. Use a stable id from your data.
Multi-step wizards, autosave every 2 seconds, offline-tolerant, keyboard-first, screen-reader-honest.
Zod schema is the contract. Types, backend validation, and form validation all derive from one source.
Uncontrolled by default — inputs don't cause parent re-renders while you type.
Errors appear on blur, disappear on valid keystroke. Submit re-validates the whole schema.
Debounced 800ms mutation with optimistic UI. Draft rows in the DB, promoted on submit.
Tab order matches visual order. Enter submits from the last field. Esc cancels dialogs.
Labels tied via `htmlFor`, errors via `aria-describedby`, live regions for save-status.
The 8–15 flows a paying customer must complete. Login, create invoice, checkout, export CSV. Runs on every PR against a real preview.
Every form, every table, every state-heavy widget. Tested through the DOM the way a user uses it — not through implementation details.
Every pure function: money formatters, date math, permission checks, the Zod schemas themselves. Fast, deterministic, run in milliseconds.
Blog-only sites, brochure sites without any product surface, and anything under 5 static pages. If there's no interactive state, ship HTML + a sprinkle of JS. React earns its weight when you have forms, tables, real-time data, or long sessions.
A dashboard that lags. A form that no one wants to fill in. A legacy admin nobody will touch. Those are the good conversations.
Talk to a React engineerTell us your goals — we'll recommend the right technology honestly, even if it isn't this one.