Uncontrolled Components
An uncontrolled component lets the browser keep the current form value. React does not update state on every keystroke. Instead, you read the value when you need it, usually with a ref or during form submission.
This is still a valid React pattern. Controlled inputs are common, but not every form needs live state.
Reading Values with Refs
import { useRef } from "react";
function NewsletterForm() {
const emailRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
const email = emailRef.current.value;
console.log("Subscribe:", email);
}
return (
<form onSubmit={handleSubmit}>
<input ref={emailRef} type="email" name="email" />
<button>Subscribe</button>
</form>
);
}React renders the input, but the DOM node owns the changing value.
defaultValue and defaultChecked
Use defaultValue for an initial value that React should not keep controlling.
<input name="displayName" defaultValue="Ava" />Use defaultChecked for checkbox and radio defaults.
<input type="checkbox" name="newsletter" defaultChecked />Changing defaultValue after the input has mounted does not overwrite what the user typed. That is the point: it is only the initial value.
Reading FormData
For many simple forms, FormData is cleaner than one ref per input.
function LoginForm() {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.currentTarget);
const values = Object.fromEntries(formData);
console.log(values.email, values.password);
}
return (
<form onSubmit={handleSubmit}>
<input name="email" type="email" />
<input name="password" type="password" />
<button>Log in</button>
</form>
);
}Inputs must have name attributes for FormData to include them.
When Uncontrolled Inputs Fit
Uncontrolled inputs are useful for:
- simple forms that only need values on submit
- integrating with non-React code
- file inputs
- avoiding re-renders while typing in very large forms
They are less convenient when the UI needs to react to each change.
File Inputs
File inputs are naturally uncontrolled because browsers do not allow scripts to set file paths for security reasons.
function UploadForm() {
function handleSubmit(event) {
event.preventDefault();
const file = event.currentTarget.avatar.files[0];
console.log(file);
}
return (
<form onSubmit={handleSubmit}>
<input name="avatar" type="file" />
<button>Upload</button>
</form>
);
}Common Mistakes
Do not mix value and defaultValue on the same input. Choose controlled or uncontrolled.
Do not expect defaultValue to reset the field after the first render. To reset uncontrolled fields, call the form's reset() method or remount the form with a different key.
event.currentTarget.reset();What does defaultValue do on an uncontrolled input?
Practice Challenge
Create an uncontrolled feedback form with name, rating, and message.
Requirements:
- read values with
FormData - reset the form after submit
- include a file input for an optional screenshot
- explain which field cannot be controlled like normal text
Recap
Uncontrolled components keep form state in the DOM. They are simple and efficient for submit-only forms, but controlled components are usually better when React needs to display live feedback or derive UI from the current value.