DEV Community

Cover image for Accessing state of an uncontrolled form
Thomas Hareau
Thomas Hareau

Posted on • Updated on

Accessing state of an uncontrolled form

Controlled forms are convenient because they give a thin control over the different values. However, they tend to be a bit verbose.

On the other side, uncontrolled forms are often shorter and more readable. They let the browser natively handle the component, reducing the needed boilerplate for controlled components.

Note: a French translation of this article exists on my website

Controlled form

For example, let's take this form. We have four inputs, "diet" being disabled if the "presence" checkbox is not ticked.

Here we need to handle all fields manually. This works, but seems to be unnecessary when HTML alone handles this perfectly well.

Uncontrolled form

Let's take the same example, using an uncontrolled form.

const action = (event) => {
  event.preventDefault();

  const data = new FormData(event.currentTarget);
  console.log("Saving...", Object.fromEntries(data.entries()));
};

const App = () => {
  return (
    <div className="App">
      <form onSubmit={action}>
        <fieldset>
          <legend>Identity</legend>
          <div>
            <label for="name">Name : </label>
            <input id="name" name="name" defaultValue="Chris" />
          </div>
          <div>
            <label for="email">Email : </label>
            <input id="email" type="email" name="email" defaultValue="chris@email.test" />
          </div>
        </fieldset>

        <fieldset>
          <legend>Event</legend>
          <div>
            <label for="presence">Presence : </label>
            <input id="presence" type="checkbox" name="presence" defaultChecked />
          </div>
          <div>
            <label for="diet">Diet : </label>
            <input id="diet" name="diet" />
          </div>
        </fieldset>

        <button type="submit">Submit</button>
      </form>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

We can notice two main changes here:

  1. we have way logic (and thus fewer bugs). We don't need form values before the submit action, so why storing them?
  2. action reads value directly from the event. As it does not use React states, we can extract it outside the component, and split our code more easily.

Oh, and maybe a last point: we don't handle the disabled field anymore. Let's do it!

Accessing state using uncontrolled forms

We need to read the current value of the "presence" checkbox to disable the "diet" field. Using controlled components, it is easy. Here, less so.

A solution to this problem is to add an onChange listener on the form itself. It will provide read-only access to the current values of the form.

const App = () => {
  const [formData, setFormData] = useState(new FormData())

  return (
    <div className="App">
      <form onSubmit={action} onChange={(event) => setFormData(new FormData(event.currentTarget))}>
Enter fullscreen mode Exit fullscreen mode

And then, on the diet field, we add:

<div>
  <label for="diet">Diet : </label> 
  <input
    id="diet"
    name="diet"
    disabled={formData.get("presence") !== "on"}
  />
</div>
Enter fullscreen mode Exit fullscreen mode

Which gives this final result:

Top comments (2)

Collapse
 
naucode profile image
Al - Naucode

Hey, that was a nice read, you got my follow, keep writing 😉

Collapse
 
thhareau profile image
Thomas Hareau

Thank you very much @naubit