devtools

A floating debug panel for React Hook Form that surfaces live field values, validation errors, and dirty/touched state as you type.

Library
npm
v4.4.0
668stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
55/100Fair
Development Activity44
Maintenance36
Community52
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
64/100Good
Architecture65
Code Quality60
Innovation55
Learning Curve75

@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 postMessage bridge (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 styles prop
  • Zero-config integration — works with any Control object from react-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.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search