devtools
A floating debug panel for React Hook Form that surfaces live field values, validation errors, and dirty/touched state as you type.
Repository Health
Technical Analysis
@hookform/devtools is the official companion package for React Hook Form that renders an in-app debugging panel during development. Instead of console-logging form state or reaching for the React DevTools component tree, you drop a single <DevTool control={control} /> component into your form and get a live, collapsible side panel showing every registered field’s current value, validation errors, dirty/touched flags, and overall form status.
The panel is powered by little-state-machine for its own UI state (open/closed, collapsed, filter text) and react-simple-animate for the slide-in/out transition, keeping the devtool’s internal state fully isolated from the form it’s inspecting. It also has a built-in bridge (useExportControlToExtension) that posts form-state updates via window.postMessage so a companion browser extension can pick up the same data outside the page.
Because it reads directly from the Control object React Hook Form already produces (via useWatch and useFormState), there’s no need to wire up custom logging or wrap fields — the panel just mirrors whatever the form is doing, live, with no extra instrumentation.
What You Get
- A
<DevTool control={control} />component that renders a slide-out panel positioned at any of the four screen corners - Live field-by-field view of current values, validation errors, and dirty/touched status as the user types
- A collapsible, filterable table view (
formStateTable) for forms with many fields - A
postMessagebridge (useExportControlToExtension) that streams the same form-state data to a companion browser extension - Custom styling hooks for both the toggle button and the panel container via a
stylesprop - Zero-config integration — works with any
Controlobject fromreact-hook-form, including nested and array fields
Common Use Cases
- Debugging why a specific field’s validation error isn’t clearing after correction
- Verifying dirty/touched state before wiring up conditional “unsaved changes” warnings
- Inspecting deeply nested or array-based form values without adding temporary console.log calls
- Reviewing a multi-step form’s cumulative state while stepping through it manually in the browser
- Pairing with the React Hook Form browser extension for a persistent, out-of-page view of form state
Under The Hood
Architecture
The package is a thin React component (DevTool in src/devTool.tsx) that wraps a presentational panel (DevToolUI in src/devToolUI.tsx) inside its own StateMachineProvider. Panel visibility, collapse state, and the field-name filter live in an isolated little-state-machine store namespaced __REACT_HOOK_FORM_DEVTOOLS__, keeping the devtool’s own UI state completely separate from the Control object it inspects. DevTool reads the form via useFormContext/useWatch/useFormState and passes the live control down to Header, Panel, and formStateTable, which render the actual field/error/dirty-state rows. A parallel path in src/extension/useExportControlToExtension.ts flattens the same nested control data (via nestToFlat/proxyToObject in utils.ts) and pushes it out over window.postMessage for a companion browser extension, so the in-page panel and the extension bridge are two independent consumers of the same underlying form state rather than one depending on the other.
Tech Stack
Written in TypeScript against React (peer dependency ^16.8.0 || ^17 || ^18 || ^19) and react-hook-form as its core integration point. Panel UI state is managed with little-state-machine, transitions with react-simple-animate, styling with plain inline styles plus a small styled.tsx helper (not Emotion at runtime, despite Emotion appearing in devDependencies for the Storybook build), field flattening uses lodash/get, unique instance IDs come from uuid, and re-render-safe nested comparisons use use-deep-compare-effect. The build pipeline is Rollup (CJS/ESM/UMD outputs via rollup-plugin-typescript2 and a generated CJS entry file), with Storybook for isolated component development and Changesets for release/versioning.
Code Quality
Tests exist but are limited in scope: src/__tests__/devToolUI.spec.tsx covers keyboard accessibility of the show/close toggle using @testing-library/react and jest, and position.spec.ts covers the placement-to-CSS-position mapping — there is no visible test coverage for the extension bridge’s data-flattening logic or the panel’s field-filtering behavior. The codebase is fully typed TypeScript with tsc --noEmit run as a pre-commit hook alongside ESLint and Prettier via lint-staged and Husky, giving reasonable guardrails despite the thin test surface. Naming is consistent and the component tree is small enough that error handling is mostly a non-issue — there’s little here that can throw.
API Design
The public surface is deliberately minimal: a single <DevTool control={control} /> component that defaults control to the nearest useFormContext value if omitted, plus optional id, placement, and styles props for positioning and theming. This makes the common case a one-line addition to an existing form with zero configuration, while still allowing multi-form apps to pass an explicit control and id to disambiguate panels. The tradeoff is that customization beyond position and inline styles (e.g. reordering panel sections or filtering which fields appear) isn’t exposed as a prop — the panel’s internal layout is fixed.
Used by 3 apps in this directory
Novu
Developer Tools
Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.
OpenStatus
Monitoring · Devops
Open-source status pages and uptime monitoring with global synthetic checks, monitoring-as-code, and AI agent integration via MCP.
Tracecat
Security · Automation · AI Agents
Open-source agentic security automation platform that runs AI agents and durable workflows at scale with sandboxed execution.