Lesson 27 of 60 – Controlled Components
45%

Controlled Components

A controlled component is a form element whose value is controlled by React state. Instead of allowing the browser to manage the input value independently, React stores the value in state and updates it whenever the user changes the input.

Note: In a controlled component, React state is the source of truth for the current form value.

1. What is a Controlled Component?

A controlled component is a form element whose current value is managed by React state.

import { useState } from "react";

function App() {

    const [name, setName] = useState("");

    return (
        <input
            value={name}
            onChange={(e) => setName(e.target.value)}
        />
    );

}

Here, React state controls the value of the input.

2. React State as the Source of Truth

In a controlled component, the state contains the current value of the form element.

const [name, setName] = useState("");

<input
    value={name}
    onChange={(e) => setName(e.target.value)}
/>

The value comes from state, while onChange updates the state.

3. Basic Controlled Input

The following is a simple controlled text input.

import { useState } from "react";

function App() {

    const [name, setName] = useState("");

    return (
        <div>

            <input
                type="text"
                value={name}
                onChange={(e) => setName(e.target.value)}
            />

            <p>
                Name: {name}
            </p>

        </div>
    );

}

export default App;

4. The value Attribute

The value attribute connects an input to React state.

const [email, setEmail] = useState("");

<input
    type="email"
    value={email}
    onChange={(e) => setEmail(e.target.value)}
/>

Whenever the state changes, React updates the input value.

5. The onChange Event

The onChange event is used to update state when the user changes an input.

function handleChange(e) {

    setName(e.target.value);

}

This creates a connection between the user's input and React state.

6. Controlled Text Input

import { useState } from "react";

function App() {

    const [username, setUsername] = useState("");

    return (
        <div>

            <label>
                Username:
            </label>

            <input
                type="text"
                value={username}
                onChange={(e) =>
                    setUsername(e.target.value)
                }
            />

            <p>
                Username: {username}
            </p>

        </div>
    );

}

7. Controlled Email Input

const [email, setEmail] = useState("");

<input
    type="email"
    value={email}
    onChange={(e) => setEmail(e.target.value)}
    placeholder="Enter email"
/>

The email field always receives its current value from React state.

8. Controlled Password Input

const [password, setPassword] = useState("");

<input
    type="password"
    value={password}
    onChange={(e) =>
        setPassword(e.target.value)
    }
/>

The password input is also controlled by React state.

9. Controlled Number Input

const [age, setAge] = useState("");

<input
    type="number"
    value={age}
    onChange={(e) =>
        setAge(e.target.value)
    }
/>

The input value is stored in React state.

10. Controlled Textarea

A textarea can also be controlled using state.

const [message, setMessage] = useState("");

<textarea
    value={message}
    onChange={(e) =>
        setMessage(e.target.value)
    }
/>

The state contains the current textarea value.

11. Controlled Select

A select element can be controlled using the value attribute.

const [course, setCourse] = useState("");

<select
    value={course}
    onChange={(e) =>
        setCourse(e.target.value)
    }
>

    <option value="">
        Select Course
    </option>

    <option value="react">
        React
    </option>

    <option value="python">
        Python
    </option>

</select>

12. Controlled Checkbox

Checkboxes are controlled using the checked attribute.

const [agree, setAgree] = useState(false);

<input
    type="checkbox"
    checked={agree}
    onChange={(e) =>
        setAgree(e.target.checked)
    }
/>

The state is a boolean value: true or false.

13. Controlled Radio Buttons

Radio buttons can also be controlled with React state.

const [gender, setGender] = useState("");

<input
    type="radio"
    name="gender"
    value="male"
    checked={gender === "male"}
    onChange={(e) =>
        setGender(e.target.value)
    }
/>

<input
    type="radio"
    name="gender"
    value="female"
    checked={gender === "female"}
    onChange={(e) =>
        setGender(e.target.value)
    }
/>

14. Multiple Controlled Inputs

A form can have multiple controlled inputs.

const [name, setName] = useState("");
const [email, setEmail] = useState("");

<input
    value={name}
    onChange={(e) =>
        setName(e.target.value)
    }
/>

<input
    value={email}
    onChange={(e) =>
        setEmail(e.target.value)
    }
/>

15. Form State Object

For forms with several fields, the values can be stored in one object.

const [form, setForm] = useState({
    name: "",
    email: "",
    phone: ""
});

This keeps related form values together.

16. Updating a Form State Object

The spread operator can preserve the existing fields while updating one field.

function handleChange(e) {

    setForm({
        ...form,
        [e.target.name]: e.target.value
    });

}

17. Using the name Attribute

The name attribute identifies which field is being updated.

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

<input
    name="email"
    value={form.email}
    onChange={handleChange}
/>

18. Dynamic Field Updates

One change handler can update multiple fields when each field has a matching name property.

function handleChange(e) {

    const { name, value } = e.target;

    setForm({
        ...form,
        [name]: value
    });

}

19. Controlled Form Submission

A controlled form can be submitted using the values stored in React state.

function handleSubmit(e) {

    e.preventDefault();

    console.log(form);

}

<form onSubmit={handleSubmit}>

    {/* controlled fields */}

    <button type="submit">
        Submit
    </button>

</form>

20. Controlled Components and Validation

Because React has the current form values in state, validation can easily be performed before submission.

function handleSubmit(e) {

    e.preventDefault();

    if (form.name === "") {

        alert("Name is required");
        return;

    }

    console.log("Form submitted");

}

21. Showing Validation Messages

const [error, setError] = useState("");

function handleSubmit(e) {

    e.preventDefault();

    if (form.name === "") {

        setError("Please enter your name");
        return;

    }

    setError("");

}

The error message can then be displayed in the JSX.

{error && (
    <p>
        {error}
    </p>
)}

22. Controlled Input with Placeholder

A placeholder can provide a hint to the user while the input is empty.

const [city, setCity] = useState("");

<input
    type="text"
    value={city}
    onChange={(e) =>
        setCity(e.target.value)
    }
    placeholder="Enter your city"
/>

23. Resetting Controlled Inputs

To clear a controlled form, reset the state values.

function resetForm() {

    setForm({
        name: "",
        email: "",
        phone: ""
    });

}

Because the inputs receive their values from state, they are cleared automatically after the state changes.

24. Controlled Component with Button

import { useState } from "react";

function App() {

    const [name, setName] = useState("");

    function showName() {

        alert(name);

    }

    return (
        <div>

            <input
                value={name}
                onChange={(e) =>
                    setName(e.target.value)
                }
            />

            <button onClick={showName}>
                Show Name
            </button>

        </div>
    );

}

export default App;

25. Controlled Components vs Normal Inputs

A controlled input gets its value from React state.

const [name, setName] = useState("");

<input
    value={name}
    onChange={(e) =>
        setName(e.target.value)
    }
/>

React knows the current value of the input and can use it for validation, display, submission, and other application logic.

26. Controlled Components and User Interface

Controlled components make it easy to react to user input and update other parts of the interface.

const [name, setName] = useState("");

return (
    <div>

        <input
            value={name}
            onChange={(e) =>
                setName(e.target.value)
            }
        />

        <h2>
            Welcome, {name}
        </h2>

    </div>
);

27. Complete Controlled Login Form

import { useState } from "react";

function App() {

    const [form, setForm] = useState({
        email: "",
        password: ""
    });

    function handleChange(e) {

        setForm({
            ...form,
            [e.target.name]: e.target.value
        });

    }

    function handleSubmit(e) {

        e.preventDefault();

        console.log(form);

    }

    return (
        <form onSubmit={handleSubmit}>

            <input
                type="email"
                name="email"
                value={form.email}
                onChange={handleChange}
                placeholder="Email"
            />

            <br />

            <input
                type="password"
                name="password"
                value={form.password}
                onChange={handleChange}
                placeholder="Password"
            />

            <br />

            <button type="submit">
                Login
            </button>

        </form>
    );

}

export default App;

28. Common Controlled Component Mistake

A common mistake is using a value without providing a way to update the state.

For example:

const [name, setName] = useState("");

<input
    value={name}
/>

The input is controlled by name, but there is no onChange handler to update it.

A controlled input normally needs both a value and a way to update that value.

<input
    value={name}
    onChange={(e) =>
        setName(e.target.value)
    }
/>

29. Controlled Components Workflow

The basic workflow of a controlled component is:

  1. User types or changes a form field.
  2. The onChange event runs.
  3. The event handler reads the new value.
  4. React state is updated.
  5. React renders the component again.
  6. The input receives the updated state value.
User Input
     ↓
onChange
     ↓
setState()
     ↓
React State
     ↓
Re-render
     ↓
Updated Input

30. Controlled Components Best Practices

  • Keep important form values in React state.
  • Use value for controlled text inputs.
  • Use checked for controlled checkboxes.
  • Use onChange to update form state.
  • Use meaningful name attributes.
  • Use one state object for related form fields when appropriate.
  • Validate data before submission.
  • Use onSubmit for form submission.
  • Reset state when you need to clear a controlled form.
  • Keep the form state and displayed input value synchronized.

📌 Key Points

  • A controlled component is controlled by React state.
  • The value attribute connects an input to state.
  • The onChange event updates the state.
  • Checkboxes commonly use checked.
  • Radio buttons can be controlled using state.
  • Select elements can be controlled using value.
  • Textarea elements can also be controlled.
  • Multiple form fields can be stored in one state object.
  • Controlled components make validation and form processing easier.
  • React state acts as the source of truth for the form value.

🧠 Quick Quiz

Question: What makes a form element a controlled component in React?