Skip to content
beginner Phase 8 · React

Controlled Components

Manage form inputs with React state for full control over form data.

30m
0 problems
Topic Progress 0%

Controlled Inputs

Controlled Inputs

How Controlled Inputs Work

  1. Input value is bound to state: value={state}
  2. onChange updates state: onChange={(e) => setState(e.target.value)}
  3. State changes trigger re-render
  4. Input displays new value

Text Input

function TextInput() {
  const [value, setValue] = useState("");

  return (
    <div>
      <input
        type="text"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        placeholder="Type something..."
      />
      <p>You typed: {value}</p>
    </div>
  );
}

Checkbox

function Checkbox() {
  const [isChecked, setIsChecked] = useState(false);

  return (
    <div>
      <input
        type="checkbox"
        checked={isChecked}
        onChange={(e) => setIsChecked(e.target.checked)}
      />
      <label>I agree to the terms</label>
    </div>
  );
}

Select

function Select() {
  const [selected, setSelected] = useState("");

  return (
    <select value={selected} onChange={(e) => setSelected(e.target.value)}>
      <option value="">Select an option</option>
      <option value="apple">Apple</option>
      <option value="banana">Banana</option>
      <option value="cherry">Cherry</option>
    </select>
  );
}

Textarea

function Textarea() {
  const [text, setText] = useState("");

  return (
    <div>
      <textarea
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="Enter your message..."
      />
      <p>Characters: {text.length}</p>
    </div>
  );
}

Multiple Inputs

Multiple Inputs

Single Handler for Multiple Inputs

function Form() {
  const [formData, setFormData] = useState({
    firstName: "",
    lastName: "",
    email: "",
    age: ""
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData((prev) => ({
      ...prev,
      [name]: value
    }));
  };

  return (
    <form>
      <input
        name="firstName"
        value={formData.firstName}
        onChange={handleChange}
        placeholder="First Name"
      />
      <input
        name="lastName"
        value={formData.lastName}
        onChange={handleChange}
        placeholder="Last Name"
      />
      <input
        name="email"
        type="email"
        value={formData.email}
        onChange={handleChange}
        placeholder="Email"
      />
      <input
        name="age"
        type="number"
        value={formData.age}
        onChange={handleChange}
        placeholder="Age"
      />
    </form>
  );
}

Nested State

function ProfileForm() {
  const [formData, setFormData] = useState({
    name: "",
    address: {
      street: "",
      city: "",
      state: "",
      zip: ""
    }
  });

  const handleChange = (e) => {
    const { name, value } = e.target;
    const keys = name.split(".");

    setFormData((prev) => {
      const newData = { ...prev };
      let current = newData;
      for (let i = 0; i < keys.length - 1; i++) {
        current[keys[i]] = { ...current[keys[i]] };
        current = current[keys[i]];
      }
      current[keys[keys.length - 1]] = value;
      return newData;
    });
  };

  return (
    <form>
      <input name="name" value={formData.name} onChange={handleChange} />
      <input name="address.street" value={formData.address.street} onChange={handleChange} />
      <input name="address.city" value={formData.address.city} onChange={handleChange} />
    </form>
  );
}

Resetting Forms

function Form() {
  const [formData, setFormData] = useState({ name: "", email: "" });

  const handleSubmit = (e) => {
    e.preventDefault();
    // Submit logic
    setFormData({ name: "", email: "" }); // Reset
  };
}

Validation

Validation

Basic Validation

function Form() {
  const [formData, setFormData] = useState({ email: "", password: "" });
  const [errors, setErrors] = useState({});

  const validate = () => {
    const newErrors = {};

    if (!formData.email) {
      newErrors.email = "Email is required";
    } else if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(formData.email)) {
      newErrors.email = "Invalid email format";
    }

    if (!formData.password) {
      newErrors.password = "Password is required";
    } else if (formData.password.length < 8) {
      newErrors.password = "Password must be at least 8 characters";
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (validate()) {
      // Submit
    }
  };
}

Real-time Validation

function Form() {
  const [formData, setFormData] = useState({ email: "" });
  const [errors, setErrors] = useState({});

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData((prev) => ({ ...prev, [name]: value }));

    // Validate on change
    if (name === "email") {
      if (!value) {
        setErrors((prev) => ({ ...prev, email: "Email is required" }));
      } else if (!/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value)) {
        setErrors((prev) => ({ ...prev, email: "Invalid email" }));
      } else {
        setErrors((prev) => ({ ...prev, email: null }));
      }
    }
  };
}

Error Display

function Form() {
  return (
    <form>
      <div>
        <input name="email" value={formData.email} onChange={handleChange} />
        {errors.email && <span className="error">{errors.email}</span>}
      </div>
    </form>
  );
}

Quiz

1. What makes an input 'controlled'?

Question 1 options

2. How do you handle multiple inputs with one handler?

Question 2 options

3. What is the checked prop used for?

Question 3 options

4. When should you validate form data?

Question 4 options

Flashcards

Question

What is a controlled component?

Answer

A component where React state controls the form input value

Question

How do you reset a form?

Answer

Set state back to initial values

Question

What prop controls checkbox state?

Answer

The checked prop

Question

How do you display validation errors?

Answer

Check if errors exist and render error messages

Revision Notes

Key Takeaways

  • 1. Controlled inputs use React state
  • 2. One handler can manage multiple inputs
  • 3. Use checked for checkboxes
  • 4. Validate on change, blur, and submit
  • 5. Display errors next to inputs

Interview Tips

  • Show how to create controlled inputs
  • Demonstrate handling multiple inputs
  • Explain validation strategies

Cheat Sheet

Cheat Sheet

Controlled Input

<input value={val} onChange={(e) => setVal(e.target.value)} />

Multiple Inputs

<input name="email" onChange={handleChange} />
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));

Checkbox

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

Validation

const validate = () => {
  const errors = {};
  if (!email) errors.email = "Required";
  setErrors(errors);
  return Object.keys(errors).length === 0;
};