How to Read Uncontrolled Form Values with FormData in React

Read uncontrolled form values in React by letting the DOM hold them and collecting them with new FormData on submit. No per-field state required.

5 min read

To read an uncontrolled form in React, let the DOM hold the field values and collect them with the FormData constructor when the form submits. This reads every field at once without tracking per-field state on every keystroke, and it works the same in every React version.

Leave the fields uncontrolled

An uncontrolled field has no value or checked prop. React renders it once, and the browser stores what the user types. Use defaultValue or defaultChecked only when a field needs a starting value, because those props set the initial value without controlling later edits.

App.jsxApp.jsx
<form onSubmit={handleSubmit}>
  <label>
    Name
    <input name="fullName" defaultValue="Taylor" />
  </label>
  <label>
    Email
    <input name="email" type="email" />
  </label>
  <button type="submit">Send</button>
</form>

The two inputs keep their own values in the DOM. Nothing re-renders as the user types, which is the main difference from a controlled form. The name attribute is what links each field to the data you read later, so it is required on every field you want to collect.

Read values on submit

The FormData constructor reads every named field from the form element. Call it inside the submit handler, after stopping the page reload, and pass the form element as the argument.

App.jsxApp.jsx
function handleSubmit(e) {
  e.preventDefault();
  const formData = new FormData(e.target);
  const data = Object.fromEntries(formData.entries());
  console.log(data);
}

Submitting the form logs an object such as { fullName: "Taylor", email: "..." }. Each name attribute became a key, which is why a field without a name never appears in the result.

Object.fromEntries converts the FormData entries into a plain object, but you can also pass the FormData straight to fetch as the request body. When several checkboxes share a name, each checked box contributes its value to that key.

Read one value with get

When the handler only needs a few fields, call get on the FormData object instead of converting everything. Pass the field's name to read a single value.

App.jsxApp.jsx
const email = formData.get("email");

This returns the value for the email field as a string, or null when the field is missing. Use getAll for fields that can repeat, such as several checkboxes that share a name, and use get with a file input when the user uploaded a file. A checkbox appears in FormData only when it is checked, so an unchecked box is simply absent from the result.

React 19 has a shorter alternative

In React 19 you can pass a function to the form's action prop, and React hands it the FormData directly. That path runs in a transition and does not require e.preventDefault, but the onSubmit plus FormData pattern works in every React version.

When uncontrolled is the right choice

An uncontrolled form is a good fit when you only need values at submit time, or when a form has many fields and per-keystroke updates would be noisy. A controlled form with state for every input works too, but it re-renders on every keystroke and adds boilerplate for values nobody reads until submit.

A controlled form is better when the UI must react to each edit, such as live validation or an enabled submit button that depends on other fields. The onChange guide shows that controlled pattern, and the two approaches can even be mixed within one form.

Leave most fields uncontrolled and control only the one that drives live UI. A search form, for example, can keep the query input controlled for instant results while the rest of the fields stay uncontrolled and are read once on submit.

The choice is per field, not per form, so you never have to commit the whole form to one style. Start with uncontrolled fields and add state only where the UI genuinely needs it.

What to learn next

Both approaches share the same submit event, so preventing the default page reload is the next building block. When forms grow to include validation and error messages, the forms overview steps through the full pattern.

Rune AI

Rune AI

Key Insights

  • Uncontrolled fields keep their values in the DOM.
  • Give every field a name attribute.
  • Read all values at once with new FormData(e.target).
  • Use formData.get for one value or Object.fromEntries for all.
  • Call e.preventDefault so the page does not reload.
RunePowered by Rune AI

Frequently Asked Questions

Do I need state for an uncontrolled form?

No. The browser stores each field's value. You read them all at once with FormData when the form submits, so no per-field state is needed.

What does new FormData(e.target) return?

A FormData object holding every named field in the submitted form. You can pass it directly to fetch or convert it with Object.fromEntries.

Does every field need a name attribute?

Yes. FormData uses the name attribute as the key, so an input without a name is not included in the collected data.

Conclusion

Leave fields uncontrolled, give each one a name, and read them all at once with new FormData on submit. FormData works in every React version and keeps large forms free of per-field state.