Controlled vs Uncontrolled Inputs
Every form input in React is either controlled (React owns the value via state) or uncontrolled (the DOM owns the value, accessed via a ref). Understanding when each is appropriate prevents performance issues and makes integrations with third-party libraries work correctly.
Controlled vs Uncontrolled — The Difference
import { useState, useRef } from 'react';
// CONTROLLED — React state drives the input value
function ControlledForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
// Re-renders on every keystroke — acceptable for small forms
// Validation on every change is easy (use value directly)
// Can programmatically set value at any time
return (
<form onSubmit={e => { e.preventDefault(); /* use email, password directly */ }}>
<input
type="email"
value={email} // ← React controls the value
onChange={e => setEmail(e.target.value)}
/>
<input
type="password"
value={password}
onChange={e => setPassword(e.target.value)}
/>
<button type="submit">Login</button>
</form>
);
}
// UNCONTROLLED — DOM owns the value, accessed via ref on submit
function UncontrolledForm() {
const emailRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
function handleSubmit(e: React.FormEvent) {
e.preventDefault();
const email = emailRef.current?.value;
const password = passwordRef.current?.value;
// validate and submit
}
return (
<form onSubmit={handleSubmit}>
<input type="email" ref={emailRef} defaultValue="" /> {/* defaultValue, not value */}
<input type="password" ref={passwordRef} />
<button type="submit">Login</button>
</form>
);
}
// Use uncontrolled for:
// - File inputs (value is read-only, always uncontrolled)
// - Integration with non-React libraries (e.g., custom rich-text editors)
// - Large forms where re-render-per-keystroke is too expensive
// react-hook-form uses uncontrolled inputs by default for this reasonWhen to Use Each
- Controlled inputs: when you need to validate on every keystroke, enable/disable buttons based on values, or format input as the user types (phone number, credit card)
- Uncontrolled inputs: high-frequency updates that don't need immediate validation, long forms with many fields, file inputs (always uncontrolled)
- react-hook-form default: uncontrolled — registers a ref on each input; only reads values on submit/validate trigger. Result: near-zero re-renders compared to fully controlled forms
- Controller component (from RHF): wraps controlled third-party inputs (DatePicker, Select from react-select) to work with react-hook-form's ref-based system
Tip
Tip
Practice Controlled vs Uncontrolled Inputs in small, isolated examples before integrating into larger projects. Breaking concepts into small experiments builds genuine understanding faster than reading alone.
Forms collect user input — each input type serves a different purpose
Practice Task
Note
Practice Task — (1) Write a working example of Controlled vs Uncontrolled Inputs from scratch without looking at notes. (2) Modify it to handle an edge case (empty input, null value, or error state). (3) Share your solution in the Priygop community for feedback.
Quick Quiz
Common Mistake
Warning
A common mistake with Controlled vs Uncontrolled Inputs is skipping edge case testing — empty inputs, null values, and unexpected data types. Always validate boundary conditions to write robust, production-ready react code.
Key Takeaways
- Every form input in React is either controlled (React owns the value via state) or uncontrolled (the DOM owns the value, accessed via a ref).
- Controlled inputs: when you need to validate on every keystroke, enable/disable buttons based on values, or format input as the user types (phone number, credit card)
- Uncontrolled inputs: high-frequency updates that don't need immediate validation, long forms with many fields, file inputs (always uncontrolled)
- react-hook-form default: uncontrolled — registers a ref on each input; only reads values on submit/validate trigger. Result: near-zero re-renders compared to fully controlled forms