In React, form elements such as <input>, <textarea>, and <select> can be managed in two main ways: controlled and uncontrolled components.
The key difference is who controls the form data — React’s state or the browser’s DOM.
? Goal: Understand when to use controlled vs uncontrolled form components.
A controlled component is one where form data is handled by React through component state. The input value is tied to a state variable, and any change updates the state.
// Controlled component: React state is the single source of truth
import { useState } from "react";
function ControlledInput() {
const [name, setName] = useState("");
function handleChange(e) {
setName(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
alert(`Hello, ${name}!`);
}
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={name}
onChange={handleChange}
placeholder="Enter your name"
/>
<button type="submit">Submit</button>
</form>
);
}
name is stored in React state using useState("").value={name} makes the input fully controlled by React.onChange updates the state on every keystroke.An uncontrolled component keeps the form data inside the DOM instead of React’s state. You access values using refs instead of state.
// Uncontrolled component: value is read directly from the DOM via a ref
import { useRef } from "react";
function UncontrolledInput() {
const inputRef = useRef();
function handleSubmit(e) {
e.preventDefault();
alert(`Hello, ${inputRef.current.value}!`);
}
return (
<form onSubmit={handleSubmit}>
<input type="text" ref={inputRef} placeholder="Enter your name" />
<button type="submit">Submit</button>
</form>
);
}
useRef() creates a ref object attached to the input.inputRef.current.value reads the value directly from the DOM.| Aspect | Controlled Component | Uncontrolled Component |
|---|---|---|
| Data Handling | Managed by React via state | Managed by the DOM |
| Accessing Value | Via state variable |
Via ref |
| Validation | Easy to validate dynamically while typing | Requires manual DOM access or native validation |
| Re-rendering | Re-renders on each input change | No re-render on input changes |
| Best For | Complex forms needing validation and dynamic UI | Simple or one-time input forms |
useRef() when you only need the value once (e.g., on submit) and don’t need reactivity.ControlledLogin component with email and password controlled by state.UncontrolledLogin version using refs for both inputs.Goal: Practice managing form elements through React’s state vs directly via the DOM using refs, and understand when each approach is most effective.