Handling Forms in React: Controlled vs. Uncontrolled Components
Forms are a crucial part of any web application, and in React, we primarily handle forms using either controlled or uncontrolled components. Understanding the difference between these two approaches can help you choose the right one for your project.
Controlled Components
In controlled components, React fully manages the form state. The component's state dictates the form’s values, and any changes are handled via event handlers.
Example of a Controlled Input
import { useState } from "react";
function ControlledForm() {
const [name, setName] = useState("");
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
alert(`Submitted Name: ${name}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name: <input type="text" value={name} onChange={handleChange} />
</label>
<button type="submit">Submit</button>
</form>
);
}
Pros of Controlled Components
✅ Easier to validate and manipulate data. ✅ Fully in sync with React’s state. ✅ More predictable behavior.
Cons of Controlled Components
❌ Can become verbose for large forms. ❌ Re-renders on every keystroke, potentially affecting performance.
Uncontrolled Components
Uncontrolled components rely on the DOM itself to manage state. Instead of using React state, we use refs to access form values when needed.
Example of an Uncontrolled Input
import { useRef } from "react";
function UncontrolledForm() {
const inputRef = useRef<HTMLInputElement>(null);
const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
alert(`Submitted Name: ${inputRef.current?.value}`);
};
return (
<form onSubmit={handleSubmit}>
<label>
Name: <input type="text" ref={inputRef} />
</label>
<button type="submit">Submit</button>
</form>
);
}
Pros of Uncontrolled Components
✅ Can be more performant, especially in large forms.
✅ Less re-renders compared to controlled components.
✅ Works well with non-React libraries (e.g., integrating third-party form controls).
Recommended by LinkedIn
Cons of Uncontrolled Components
❌ Harder to validate inputs in real-time.
❌ Not in sync with React’s state, making debugging trickier.
When to Use Each Approach?
Use Case Recommended Approach
Simple forms with validation => ✅ Controlled
Large forms with many fields => ✅ Uncontrolled
Forms needing real-time updates => ✅ Controlled
Integrating with third-party UI => ✅ Uncontrolled
Hybrid Approach: Best of Both Worlds
Sometimes, using a mix of both approaches works best! You can initialize inputs using refs (uncontrolled) and then control their state when needed.
import { useRef, useState } from "react";
function HybridForm() {
const inputRef = useRef<HTMLInputElement>(null);
const [submittedValue, setSubmittedValue] = useState("");
const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
if (inputRef.current) {
setSubmittedValue(inputRef.current.value);
}
};
return (
<form onSubmit={handleSubmit}>
<label>
Name: <input type="text" ref={inputRef} />
</label>
<button type="submit">Submit</button>
{submittedValue && <p>Submitted Name: {submittedValue}</p>}
</form>
);
}
Final Thoughts
Are you using controlled or uncontrolled components in your projects? Let me know your thoughts! 🚀