🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Uncontrolled Forms: Letting the DOM Hold the Value

Learn uncontrolled forms in React: reading values with refs, the FormData API, and when uncontrolled beats controlled forms.

Total XP: 0|💻 react XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Uncontrolled fundamentals.

Quick Quiz //

In an uncontrolled form, who manages an input's current value?


🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Controlled forms make React state the source of truth for every keystroke. Uncontrolled forms flip that, letting the DOM manage input values and reading them only on demand via refs or the FormData API. This lesson covers when that tradeoff pays off.

1Letting the DOM Hold the Value

In a controlled form, React state is the single source of truth for every field's value, updated on every keystroke. An uncontrolled form flips this: the DOM input manages its own value internally, and the value is only read — typically via a ref — at the exact moment it's needed, like submission.

2Reading Values with a Ref

An uncontrolled input needs no value or onChange prop — just a ref and, optionally, a defaultValue for its initial content. The current value is read directly from the ref's current.value property whenever needed, typically inside a submit handler.

3The FormData API

For an entire form of uncontrolled fields, the native FormData API reads every named input's current value from the form element directly, given to the submit handler's event, without needing a separate ref on every single field.

4When Uncontrolled Wins

Uncontrolled forms are well suited to large, simple forms with no real-time validation or per-keystroke formatting needs — they trigger fewer re-renders, require less code, and integrate naturally with native HTML form submission and React 19's Actions and Server Actions.

5Step-by-Step Breakdown

Letting the DOM Hold the Value. You've already mastered controlled forms, where React's state is the single source of truth for every keystroke. An uncontrolled form flips that: the actual DOM input holds its own value, and you only reach in and read it — typically via a ref — at the moment you actually need it, like on submit.

Reading Values with a Ref. An uncontrolled input needs no value or onChange prop at all — just a ref and, optionally, a defaultValue for its starting content. You read the current value directly from inputRef.current.value whenever you need it, typically inside a submit handler.

In an uncontrolled input using ref={emailRef} with no value prop, what triggers a React re-render as the user types?

  • Nothing — the DOM manages the value internally, with no React re-render per keystroke
  • React re-renders on every keystroke, same as a controlled input

The FormData API. For a whole form of uncontrolled inputs, you don't need a ref on every single field — the native FormData API can read every named input's value from the form element itself, given to the submit handler's event. This pairs especially well with React 19's Actions.

When Uncontrolled Wins. Uncontrolled forms shine for large, simple forms with no real-time validation or formatting needs — fewer re-renders (better for forms with dozens of fields), less code, and a more natural fit with native HTML form submission and React 19's Actions and Server Actions.

Which is a better fit for the uncontrolled pattern: a 20-field signup form submitted once, or a live search box filtering results as you type?

  • The 20-field signup form, since it doesn't need per-keystroke reactions
  • The live search box, since it needs to react to every keystroke

Mastery Achieved. You now understand uncontrolled forms: letting the DOM hold input values, reading them with refs or the FormData API, and recognizing when this pattern's simplicity and performance beat a fully controlled approach. Next, you'll learn React Hook Form, the library that formalizes uncontrolled forms with validation built in.

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

FormData is fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Uncontrolled Inputs Still Need Proper Labels and Error Association

Because uncontrolled inputs skip React-driven live feedback, it's especially important to ensure standard HTML accessibility (label htmlFor/id association, aria-invalid, aria-describedby for errors) is present, since there's no controlled re-render to lean on for dynamic ARIA updates.

SEO Implications

  • 1

    Uncontrolled Forms Pair Naturally with Progressive Enhancement

    Because uncontrolled forms rely on native HTML form submission semantics, they can work even before client JavaScript fully hydrates in a server-rendered app, which benefits both resilience and initial interactivity metrics.

Best Practices

Use FormData for Multi-Field Forms Instead of a Ref Per Field

Reading every field through FormData(formElement) after submission is simpler and less repetitive than creating and attaching a separate ref for each individual input.

Reserve Uncontrolled Forms for Cases Without Live Feedback Needs

If a form needs real-time validation, character counters, or conditional field visibility based on live input, a controlled (or React Hook Form-managed) approach is usually a better fit than pure refs.

Frequent Bugs

THE BUG

Trying to read an uncontrolled input's value immediately after a state update, but getting a stale result.

THE FIX

Uncontrolled input values live entirely in the DOM, not React state — read them directly from the ref (or via FormData) at the moment they're needed, rather than trying to track them through a React state variable.

THE BUG

A defaultValue passed to an uncontrolled input doesn't update when its underlying prop changes.

THE FIX

defaultValue, as its name implies, only sets the initial value — the DOM owns the field afterward and won't sync to later prop changes. If the value genuinely needs to update programmatically after the initial render, the field should be controlled instead.

Real-World Examples

A Large Uncontrolled Signup Form

A 15-field signup form has no real-time validation requirements — errors are only shown after submission. Building it with uncontrolled inputs and reading all fields via FormData(e.target) on submit avoids the re-render overhead of 15 separate pieces of controlled state, while keeping the implementation simple.

function SignupForm() {
  function handleSubmit(e) {
    e.preventDefault();
    const formData = new FormData(e.target);
    const payload = Object.fromEntries(formData.entries());
    submitSignup(payload);
  }
  return (
    <form onSubmit={handleSubmit}>
      <input name="firstName" /> <input name="lastName" /> <input name="email" />
      {/* ...more fields, no state needed for any of them */}
    </form>
  );
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Trying to programmatically update an uncontrolled input's displayed value after the initial render

// To programmatically update an uncontrolled field inputRef.current.value = 'new value';

The Solution //

defaultValue only sets the initial value; changing it later doesn't update the DOM's current value. To update it programmatically, set inputRef.current.value directly, or switch that field to a controlled input.

The Error //

Forgetting the `name` attribute on an uncontrolled input, breaking FormData reads

// Wrong: no name, FormData can't find this field <input ref={emailRef} /> // Correct <input name="email" ref={emailRef} />

The Solution //

FormData reads fields by their name attribute, not by any React-specific identifier. Every field intended to be read via FormData must have a proper name attribute set.

Lesson Glossary

[01]Uncontrolled Input

A form input whose value is managed by the DOM itself, not by React state.

Code Preview
<input ref={inputRef} defaultValue="" />

[02]defaultValue

A prop setting an uncontrolled input's initial value, without controlling it afterward.

Code Preview
defaultValue="initial text"

[03]FormData

A native browser API for reading every named field's value from a form element at once.

Code Preview
new FormData(formElement)

[04]Progressive Enhancement

Building forms that work with native HTML submission even before client JavaScript fully loads.

Code Preview
<form onSubmit={handleSubmit}>

Continue Learning