A Controlled Component is a form input whose value is controlled by React state.
- The source of truth is the React state, not the DOM.
- You update the value via setState (or useState) and pass it as value to the input.
- Every change triggers an event handler (onChange) that updates the state.
import React, { useState } from "react";
function ControlledExample() {
const [name, setName] = useState("");
const handleChange = (event) => {
setName(event.target.value); // React state updates
};
const handleSubmit = (event) => {
event.preventDefault();
console.log("Submitted Name:", name);
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name} // controlled by React
onChange={handleChange}
/>
<button type="submit">Submit</button>
</form>
);
}
export default ControlledExample;Key points:
- React always knows the current value.
- Easier to validate and manipulate in real-time.
- More code but predictable.
An Uncontrolled Component is a form input that keeps its own state in the DOM instead of React state.
- The source of truth is the DOM, not React.
- You use a ref to directly read the value from the DOM when needed.
import React, { useRef } from "react";
function UncontrolledExample() {
const nameRef = useRef();
const handleSubmit = (event) => {
event.preventDefault();
console.log("Submitted Name:", nameRef.current.value); // read from DOM
};
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={nameRef} /> {/* DOM manages value */}
<button type="submit">Submit</button>
</form>
);
}
export default UncontrolledExample;Key points:
- React doesn't track value changes in real-time.
- Less code but harder to validate dynamically.
- Closer to traditional HTML form handling.
| Feature | Controlled Component | Uncontrolled Component |
|---|---|---|
| Data source | React state | DOM (via refs) |
| Value access | state variable | ref.current.value |
| Change handling | onChange updates state | No state update, changes happen in DOM |
| Validation | Easy (real-time in onChange) | Harder (need to manually read from DOM) |
| Code verbosity | More verbose | Less verbose |
| Use case | Dynamic forms, instant validation, UI sync | Simple forms, integrating non-React libraries |