🔄 Controlled vs Uncontrolled Components in React: What I Learned About Forms


Introduction:
When I first started learning React, forms were honestly a little intimidating. In vanilla HTML, forms just work — but in React, there’s this whole thing about controlled and uncontrolled components. At first, I didn’t really get the difference. But after working on a few small projects (like a quiz app and a user login form), it started to click.
So in this post, I’ll try to break down the key differences between controlled and uncontrolled components, and share what worked best for me when handling forms.
What Are Controlled Components?
Controlled components are form inputs (like <input>
or <textarea>
) that are completely managed by React state. That means every time the user types something, React is updated with the new value.
const [email, setEmail] = useState("");
return (
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
);
Here, the input is “controlled” by the email
state. It might feel like extra work, but the benefit is that you always know what the input’s value is — and you can add validation, formatting, or other logic very easily.
What Are Uncontrolled Components?
Uncontrolled components are more like traditional HTML inputs. Instead of using React state, you let the DOM manage the input’s value and use a ref
to access it when needed.
const inputRef = useRef();
const handleSubmit = () => {
console.log(inputRef.current.value);
};
return <input type="text" ref={inputRef} />;
It’s easier to set up, but harder to track changes in real-time. I found this useful for simple inputs where I didn’t care about validation or updating UI live — like a file upload input.
My Experience & What I Prefer
At first, I leaned toward uncontrolled components just because they were simpler. But as I built more things — like login forms and user profiles — controlled components gave me more power.
I could show validation messages, disable the submit button until all fields were valid, and reset forms easily. So now I almost always use controlled components unless I have a good reason not to.
Best Practices I Picked Up:
âś… Use controlled components for anything dynamic or with validation
âś… Use form libraries like react-hook-form
or Formik
if forms get big
âś… Always name your inputs clearly (it helps when updating state!)
✅ Keep form logic in one place — avoid spreading handlers everywhere
Conclusion
Controlled and uncontrolled components aren’t as scary as they sound. Once I got some hands-on practice, I realized they’re just two ways of managing the same thing — input values. Controlled inputs give me more flexibility, so that’s what I usually go with now.
If you're just starting with React forms, try both methods and see what makes sense to you. That’s what helped me most!
Subscribe to my newsletter
Read articles from Mark Adrian directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
