DEV Community

Cover image for My Personal Experience with the “Changing from Uncontrolled input to Controlled” Error
Amrita-padhy
Amrita-padhy

Posted on

My Personal Experience with the “Changing from Uncontrolled input to Controlled” Error

When I first started building forms in my current project, I ran into this error:

hook.js:608 A component is changing an uncontrolled input to be controlled. This is likely caused by the value changing from undefined to a defined value, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component.
Enter fullscreen mode Exit fullscreen mode

It appeared in my browser console like an angry red flag every time my form loaded.

At first, I didn’t fully understand why React was upset. But after digging in, I realized the issue was this:

The root cause
An uncontrolled input becomes controlled if its value prop changes from undefined to a defined value after the first render.

Example of the problem:

<input value={formData.name} onChange={handleChange} />

Enter fullscreen mode Exit fullscreen mode

If formData.name is undefined at first (maybe the data is still loading), React treats the input as uncontrolled.
But when the data finally loads and formData.name becomes "User", React sees that as switching from uncontrolled → controlled.

How I fixed it
I ensured the value was always defined, even before data loaded:

<input
  value={formData.name ?? ""}
  onChange={handleChange}
/>

Enter fullscreen mode Exit fullscreen mode

Or, when using React Hook Form, I provided defaultValue explicitly:

<input {...register("name")} defaultValue="" />

Enter fullscreen mode Exit fullscreen mode

For controlled components wrapped with Controller:

<Controller
  name="username"
  control={control}
  defaultValue="" // important!
  render={({ field }) => <InputText {...field} />}
/>

Enter fullscreen mode Exit fullscreen mode

Lesson learned

  • Always decide upfront if your input will be controlled or uncontrolled.
  • If controlled, initialize value to an empty string (or a sensible default) instead of letting it be undefined.
  • If uncontrolled, don’t bind a value prop at all — use defaultValue or refs.

This small detail saved me hours of debugging and also made me appreciate why libraries like React Hook Form handle defaults so gracefully.

Top comments (0)