How do you manage forms in React?

Forms are essential elements of interactive web applications. Learn how to master controlled and uncontrolled inputs to deliver a seamless user experience. Discover best practices for simplified management.
•
Updated on August 14, 2026
•
5 min read
Believemy logo

Differences Between "Controlled" and "Uncontrolled" Inputs

Controlled and uncontrolled inputs are two different approaches to managing user input in React forms.

In the case of controlled inputs, the form state is managed by React, and the value of each input is linked to a state variable via the `value` attribute. This approach ensures complete control over the input data and allows for validation and formatting operations before form submission.

In the case of uncontrolled inputs, React does not manage the input state. Instead, the value of the inputs is determined by the DOM via the `defaultValue` attribute. Data is retrieved directly from the DOM, usually upon form submission. While this approach is simpler to implement, it can lead to difficulties when performing real-time data validation or finely controlling form behavior.

 

Controlled Input

A "controlled" input is an input that is managed via state. Its value is linked to this state and cannot be modified directly. The only way to change its value is by using a useState hook and the onChange event.

JSX
const ControlledInput = () => {
  const [value, setValue] = useState("");
  return (
    <input value={value} 
           onChange={(e) => { setValue(e.target.value) }} />
  )
}

The issue with this approach is that every time the user types a letter, it causes a re-render of the input. This is because the input's value is not managed by the DOM but by React.

Here is an example of a simple form with controlled inputs:

JSX
const SignUp = () => {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');

  const handleSubmit = () => {
    alert(`${name} ${email}`);
  };

  return (
    <form>
      <label htmlFor="name">Name:&nbsp;</label>
      <input type="text"
             id="name" 
             value={name} 
             onChange={(e) => setName(e.target.value)} />
             
      <label htmlFor="email">Email:&nbsp;</label>   
      <input type="email"
             id="email"
             value={email} 
             onChange={(e) => setEmail(e.target.value)} />
             
      <button onClick={handleSubmit}>Submit</button>
    </form>
  );
};

Controlled inputs offer several advantages. By controlling the input state, it's easy to implement real-time validations and prevent invalid submissions before sending the data.

However, this approach can lead to more code, especially for complex forms. Each input requires the creation of a state variable, and frequent re-renders occur when updating values. These drawbacks can impact application performance for more complex and large-scale forms.

To optimize performance, a common trick is to use a debounce to reduce the number of re-renders when a user is typing. This avoids unnecessary DOM updates on every keystroke, resulting in a smoother user experience.

 

Uncontrolled Input

An "uncontrolled" input is an input whose value is managed by the DOM, and it does so efficiently. Remember that it's a native HTML component designed to interact with the user.

To make an input "uncontrolled" in React, simply use the special attribute `defaultValue`.

JSX
const UncontrolledInput = () => {
  return <input defaultValue={''} />  
}

Here is the same form example as above, but this time with uncontrolled inputs:

JSX
const SignUp = () => {
  
  const handleSubmit = (evt) => {
    const form = evt.currentTarget;
    // Using FormData (recommended)
    // Don't forget to add the name attribute to inputs
    const formData = new FormData(form)

    const name = formData.get('name');
    const email = formData.get('email');

    /* Without FormData 
      const name = form.elements.name.value;
      const email = form.elements.email.value;
    */
     
    alert(`${name} ${email}`);

    /* Resets the form */
    form.reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <label htmlFor="name">Name:&nbsp;</label>
      <input type="text"
             id="name" 
             name="name"/>
             
      <label htmlFor="email">Email:&nbsp;</label>   
      <input type="email"
             id="email"
             name="email"/>
             
      <button type="submit">Submit</button>
    </form>
  );
};

Here, there will be no re-render.

Note that since the inputs are wrapped inside a form, the `defaultValue` attribute is not mandatory.

Uncontrolled inputs are easier to implement for simple cases where real-time validation is not essential.

They avoid creating state variables for each input. However, this approach limits the ability to perform real-time data validation and is more challenging to set up. Data is only retrieved upon form submission.

 

When to Use Controlled or Uncontrolled Inputs?

Use a controlled input:

  • If you need to manage a value linked to state and perform both reading and writing by modifying this state. For example, in an "Autocomplete" or incremental search.
  • For complex forms with advanced state management and validation.
  • Be cautious as it can quickly become complex to manage, but it offers more flexibility at that level.

 

Use an uncontrolled input:

  • For simple forms with basic validation needs.
  • If you want to perform an action (simple validation) when the input value changes. Use just the onChange event (avoid using useEffect and state).
  • If you just want to read the value, you can do so using a ref with useRef, for example.

 

Conclusion

We have seen the difference between controlled and uncontrolled inputs.

We have also seen when to use them in general.

Generally speaking, using uncontrolled inputs is often the best way in most cases. It avoids re-renders, resulting in a smoother interface. The disadvantage (negligible, in my opinion) is that data validation and error message display, if needed, occur upon form submission.

To simplify working with forms (validations, complex forms), I recommend using the React Hook Form library.

 

References:

 

Category: Developers

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.

Believemy logo
Comments (0)

You need to be logged in to comment on this article: log in or sign up.

Read next

Class-based component VS Functional Component with React

Have you always wondered about the difference between a component using a class and a component in the form of a function with React? Then this article is for you!

December 9, 2024

Creating a form with dynamic labels

The more modern a form, the more engaging it is. In this article, we'll look at how to create a form with dynamic labels that will increase the engagement of your forms and make your users want to fill them in.

December 9, 2024

Detecting the shift key on a form with JavaScript

Whether it's for your registration or login forms, or even on your password change pages, warning your users when they use the shift key on their keyboard will considerably improve their experience on your site. In this article, we'll show you how to do this very easily!

December 9, 2024

Animating a checkbox with CSS

Animating the checkboxes in your forms can greatly improve the experience your users have and will undeniably increase their desire to fill them in. A form that's more fun to fill in is a form that your users will fill in more often. In this article, we'll look at how to animate a checkbox using CSS!

December 9, 2024

Creating a glassmorphic connection form in HTML and CSS

In this article, we're going to create a form with a glassmorphic design. Modern effect guaranteed!

December 9, 2024

Respecting SOLID principles with React

The SOLID principles are a set of five fundamental programming concepts. They are mostly applied in OOP (Object-Oriented Programming). They can also be applied elsewhere. They are indispensable in software architecture. To present these principles, I've chosen to use Javascript rather than Typescript, so as not to weigh down the examples. We're going to apply these principles to a simple "Todo List".

December 11, 2024

How to use React's useEffect and useRef hooks?

Discover the best practices to adopt with useEffect and useRef, what they're for and how to use them in the right way.

December 11, 2024

Understanding .env files with ReactJS

Find out how to really use the .env file with React or NextJS so you never make a mistake again.

December 9, 2024

Become the solopreneur you dream of being.

First project, career change, business launch: access our courses, practice on real-world cases, and move forward with clear guidance.