How to Update Controlled Components in React

Controlled components are a fundamental pattern in React where form data is handled directly by the component’s state rather than the DOM. This article provides a straightforward guide on how to update controlled components, covering the core steps of initializing state, binding values, and using event handlers to manage user input seamlessly.

To update a controlled component in React, you must link the input’s value to a state variable and update that state whenever the user interacts with the element. Here is the step-by-step process to achieve this.

1. Initialize the State

First, use the useState hook to create a state variable that will hold the current value of your form input.

const [inputValue, setInputValue] = useState("");

2. Bind State to the Input Value

Assign the state variable to the value attribute of your form element (such as an <input>, <textarea>, or <select>). This ensures that React is the “single source of truth” for the input’s displayed value.

<input type="text" value={inputValue} />

3. Handle the Change Event

Create an event handler function that triggers whenever the user types or changes the value. This function captures the new value from the event object (e.target.value) and updates the state using the state updater function.

const handleChange = (e) => {
  setInputValue(e.target.value);
};

4. Connect the Handler to the Input

Attach your event handler to the onChange attribute of the input element. This completes the data flow: user input triggers onChange, which updates the state, causing the component to re-render with the new value.

<input type="text" value={inputValue} onChange={handleChange} />

Complete Code Example

Here is how these steps look when integrated into a functional React component:

import React, { useState } from 'react';

function UsernameForm() {
  const [username, setUsername] = useState('');

  const handleInputChange = (event) => {
    setUsername(event.target.value);
  };

  return (
    <form>
      <label htmlFor="username">Username: </label>
      <input
        type="text"
        id="username"
        value={username}
        onChange={handleInputChange}
      />
      <p>Current value: {username}</p>
    </form>
  );
}

export default UsernameForm;

Updating Multiple Controlled Components

If you have multiple inputs, you do not need a separate handler for each one. Instead, you can use a single object for your state and utilize the HTML name attribute to dynamically update the correct state key:

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

const handleFormChange = (event) => {
  const { name, value } = event.target;
  setFormData((prevData) => ({
    ...prevData,
    [name]: value,
  }));
};

// Usage in JSX:
<input name="firstName" value={formData.firstName} onChange={handleFormChange} />
<input name="lastName" value={formData.lastName} onChange={handleFormChange} />

This approach keeps your code clean, maintainable, and scalable as your forms grow in complexity.