Controlled vs Uncontrolled Forms in React
When working with forms in React, you have two main approaches for managing form data:

- Controlled Components – React controls the form data via state.
- Uncontrolled Components – The DOM handles the form data, and React accesses it using refs.
Choosing the right approach depends on your app complexity, validation needs, and interaction patterns.
Controlled Components
- A controlled form is one where React state controls the value of the input.
- This gives you full control over user input, validation, and updates.
Example – Controlled Input
- Input value is tied to React state (
value={name}). - Updates happen via
onChangehandler. - Easy to validate and manipulate input dynamically.
- Recommended for most React applications.
import React, { useState } from "react";
function ControlledForm() {
const [name, setName] = useState("");
const handleChange = (e) => {
setName(e.target.value);
};
const handleSubmit = (e) => {
e.preventDefault();
alert(`Submitted Name: ${name}`);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" value={name} onChange={handleChange} />
<button type="submit">Submit</button>
</form>
);
}
export default ControlledForm;
Uncontrolled Components
An uncontrolled form is one where the DOM manages the input state.
React doesn’t directly control the value; instead, you access it using refs.
Example – Uncontrolled Input
- Input value is managed by the DOM, not React state.
useRefaccesses the current value when needed.- Less code for simple forms.
- Harder to validate or dynamically manipulate input in real time.
import React, { useRef } from "react";
function UncontrolledForm() {
const nameRef = useRef();
const handleSubmit = (e) => {
e.preventDefault();
alert(`Submitted Name: ${nameRef.current.value}`);
};
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={nameRef} />
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledForm;
Key Differences – Controlled vs Uncontrolled
| Feature | Controlled Components | Uncontrolled Components |
|---|---|---|
| Data Flow | React state controls input | DOM handles input |
| Value | value prop tied to state | Accessed via ref |
| Validation | Easy and real-time | Manual, after submission |
| Updates | State updates trigger re-render | DOM manages updates |
| Recommended Use Case | Complex forms, dynamic updates | Simple forms, quick prototypes |
| Event Handling | onChange required | onSubmit only, optional onChange |
When to Use Which
- Use Controlled Components:
- When you need real-time validation.
- When input values affect other parts of the UI.
- For complex forms with multiple fields or dynamic behavior.
- Use Uncontrolled Components:
- For simple forms or prototypes.
- When you don’t need to monitor input changes until submission.
- For integrating non-React libraries that manipulate the DOM.
Hybrid Approach
You can also combine controlled and uncontrolled components in large forms, managing critical inputs via state while letting other inputs remain uncontrolled for simplicity.
Example – Controlled vs Uncontrolled
import React, { useState, useRef } from "react";
function FormComparison() {
const [controlledName, setControlledName] = useState("");
const uncontrolledNameRef = useRef();
const handleSubmit = () => {
alert(
`Controlled: ${controlledName}, Uncontrolled: ${uncontrolledNameRef.current.value}`
);
};
return (
<div>
<inputtype="text"
value={controlledName}
onChange={(e) => setControlledName(e.target.value)}
placeholder="Controlled"
/>
<input type="text" ref={uncontrolledNameRef} placeholder="Uncontrolled" />
<button onClick={handleSubmit}>Submit</button>
</div>
);
}
export default FormComparison;
