/Building

React Hook Form Stops Working in React 19 (and How I Fixed It)

I was updating my CMS codebase, which was built with React 18 and Next 15. When I started testing, suddenly my form inputs that use React Hook Form (RHF) started failing. The more I tested, the more issues I found.

In Next.js dev mode, if I refreshed the page, the checkbox input worked fine — it toggled as usual. But when I navigated to another page and came back, the checkbox stopped working completely. Clicking did nothing.

I also noticed the same issue with text inputs. The dirty state would not update, and because my submit button is disabled when the form is not dirty, I could not submit changes at all. The inputs felt unstable, which made debugging very frustrating.

I was debugging for hours, refactor watch() to useWatch(), solved some problems, but not all of them. I tried using AI to help, and it made things worse by suggesting too many unnecessary changes. At that point, I was close to ditching RHF and using something else.

As a last attempt, I started comparing what changed between React 18 and 19. Why did some RHF inputs still work while others did not? That is when I noticed the pattern: some inputs used register, and some used Controller.

register works by connecting the input using refs. In React 18, this was fine because rendering was predictable. But in React 19, inputs can be recreated or rehydrated differently during navigation or state updates, and RHF sometimes loses its internal connection with registered inputs.

Controller works differently. Instead of attaching by ref, it wraps the input and controls the value and onChange explicitly. That makes it more stable in React 19 because React cannot “detach” it silently.

The broken ones were using register.

Convinced that it is the problem, i refactored every input to use Controller instead. After that, everything worked normally again. No random toggle failures. No broken dirty state. No unstable behavior.

The relief when the form finally worked was ridiculous.