DEV Community

Mohamed Idris
Mohamed Idris

Posted on

Controlled Inputs or Uncontrolled Inputs in React?

When building forms in React, you might come across the terms controlled inputs and uncontrolled inputs. But why should you choose one over the other? And what exactly are they? In this post, we’ll explore the difference and why controlled inputs are generally the preferred way to handle forms in React.

What Are Controlled Inputs?

Controlled inputs in React are form elements whose values are managed by React's state. Instead of letting the input element handle its own state, we bind the value of the input field to a state variable. Whenever the input changes, the state is updated, which in turn updates the value of the input field.

Example of a controlled input:

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

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

return (
  <input type="email" value={email} onChange={handleChange} />
);
Enter fullscreen mode Exit fullscreen mode

In this case, React takes control over the input’s value, and any change the user makes to the input updates the state.

The Benefits of Controlled Inputs

  1. Centralized State Management:
    With controlled inputs, the state of the input fields is managed in one place (i.e., React’s state). This helps you avoid manually tracking multiple values across your form.

  2. Real-Time Validation:
    Controlled inputs allow for real-time validation. For example, if you want to ensure the email address is valid before the form is submitted, you can immediately check and show feedback as the user types, rather than waiting until the form is submitted.

  3. Declarative and Predictable:
    With controlled inputs, your code becomes more declarative. The input's value is explicitly controlled by the state, making it easier to reason about and debug.

  4. Easier to Handle Complex Interactions:
    When you need complex behavior like enabling/disabling fields based on other inputs, controlled inputs make this process straightforward. You can dynamically update the UI by simply modifying the state.

What About Uncontrolled Inputs?

Uncontrolled inputs, on the other hand, let the DOM handle the input state. The form element’s value is accessed via a reference (ref), and React doesn’t directly manage the state of the input.

Example of an uncontrolled input:

const emailRef = useRef();

const handleSubmit = (e) => {
  e.preventDefault();
  console.log(emailRef.current.value); // Access value directly from ref
};

return (
  <form onSubmit={handleSubmit}>
    <input type="email" ref={emailRef} />
    <button type="submit">Submit</button>
  </form>
);
Enter fullscreen mode Exit fullscreen mode

With uncontrolled inputs, React doesn’t track the value of the input, so you must use a ref to retrieve the value when needed (e.g., on form submission).

Why Choose Controlled Inputs Over Uncontrolled Inputs?

While you can use uncontrolled inputs in React, controlled inputs offer several key advantages that make them more suited for most use cases:

  • Better Validation: If you need to validate data in real time (like ensuring an email address is correct), controlled inputs make it easy to track and validate the value as the user types.

  • More Control: With controlled inputs, React takes care of updating the input state. This centralized control makes the app more predictable and manageable.

  • Easier State Management: React’s state management is one of its core strengths. Using controlled inputs lets you leverage React’s built-in features, like easy state updates and conditional rendering.

A Real-World Scenario

Imagine you have a form where the user enters their email address. If the email is invalid, you don’t want them to submit the form until it's corrected. Using uncontrolled inputs would require you to manually check the email after submission, whereas with controlled inputs, you can easily validate the email in real time as the user types.

Example with controlled input for email validation:

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

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

  // Simple email validation
  const isValidEmail = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(value);
  setError(isValidEmail ? "" : "Invalid email address");
};

return (
  <div>
    <input type="email" value={email} onChange={handleChange} />
    {error && <p>{error}</p>}
  </div>
);
Enter fullscreen mode Exit fullscreen mode

In this example, the email is validated immediately as the user types, providing a better user experience and preventing submission of invalid data.

Conclusion

While uncontrolled inputs can be useful in some cases, controlled inputs offer better flexibility, real-time validation, and more control over form data. If you need to handle complex form logic, real-time validation, or easily manage input states, controlled inputs are the way to go.


Credits: John Smilga

Top comments (0)