ReactJS
Web Development
Programming Errors
Coding Solutions
Component Interaction

A component is changing an uncontrolled input of type text to be controlled error in ReactJS

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

This React warning appears when an input starts life unmanaged by React and later becomes managed by React state. In practice, it usually means the value prop was undefined or missing on the first render, then became a real string on a later render.

Controlled Versus Uncontrolled Inputs

A controlled input gets its current value from React state:

jsx
1import { useState } from "react";
2
3export default function SearchBox() {
4  const [text, setText] = useState("");
5
6  return (
7    <input
8      type="text"
9      value={text}
10      onChange={(e) => setText(e.target.value)}
11    />
12  );
13}

An uncontrolled input lets the browser manage the current value internally:

jsx
export default function SearchBox() {
  return <input type="text" defaultValue="hello" />;
}

Both are valid patterns. The warning happens when the component switches between them.

A Typical Broken Example

jsx
1import { useState } from "react";
2
3export default function ProfileForm() {
4  const [name, setName] = useState(undefined);
5
6  return (
7    <input
8      type="text"
9      value={name}
10      onChange={(e) => setName(e.target.value)}
11    />
12  );
13}

On the first render, name is undefined, so React treats the input as uncontrolled. Once the user types, name becomes a string, and the same input becomes controlled. React warns because switching modes can produce confusing behavior.

The Standard Fix

Initialize controlled text inputs with an empty string:

jsx
1import { useState } from "react";
2
3export default function ProfileForm() {
4  const [name, setName] = useState("");
5
6  return (
7    <input
8      type="text"
9      value={name}
10      onChange={(e) => setName(e.target.value)}
11    />
12  );
13}

Now the input is controlled from the very first render, so the warning disappears.

When Data Arrives Asynchronously

This warning often appears when form data is loaded from an API. On the first render the data is missing, then later the request completes and the input receives a defined value.

jsx
1export default function ProfileForm({ user }) {
2  return (
3    <input
4      type="text"
5      value={user?.name ?? ""}
6      onChange={() => {}}
7    />
8  );
9}

The fallback ?? "" ensures that the input always receives a string.

If the field is meant to be editable, combine that with real local state:

jsx
1import { useEffect, useState } from "react";
2
3export default function ProfileForm({ user }) {
4  const [name, setName] = useState("");
5
6  useEffect(() => {
7    setName(user?.name ?? "");
8  }, [user]);
9
10  return (
11    <input
12      type="text"
13      value={name}
14      onChange={(e) => setName(e.target.value)}
15    />
16  );
17}

Do Not Mix value and defaultValue

Another common source of confusion is mixing controlled and uncontrolled props on the same element.

Bad pattern:

jsx
<input value={name} defaultValue="guest" />

Pick one model:

  • controlled: use value plus onChange
  • uncontrolled: use defaultValue and read with refs or form submission

Mixing them sends contradictory signals.

Why React Warns

React wants form elements to behave predictably. Switching modes mid-life makes it unclear whether the source of truth is the DOM or React state. That can cause lost keystrokes, stale values, and hard-to-debug form bugs.

The warning is not just stylistic. It points to real inconsistency in how the field is managed.

Common Pitfalls

The most common mistake is initializing text state with undefined or null instead of "".

Another issue is rendering value={someObject.name} before someObject exists. Use a safe fallback such as someObject?.name ?? "".

A third pitfall is conditionally adding the value prop only on some renders. If the element is controlled, keep it controlled on every render.

Summary

  • This warning means an input switched from uncontrolled to controlled.
  • For text inputs, initialize controlled state with "".
  • When data loads asynchronously, use a fallback such as ?? "".
  • Do not mix value and defaultValue on the same input.
  • Pick one model, controlled or uncontrolled, and stay consistent.

Course illustration
Course illustration

All Rights Reserved.