You are viewing a free preview of this lesson.
Subscribe to unlock all 10 lessons in this course and every other course on LearningBro.
HTML forms have their own built-in state, managed by the DOM. React gives you two approaches for working with form inputs: controlled components (the React way) and uncontrolled components (relying on the DOM). Understanding the difference helps you choose the right pattern for each situation.
In a controlled component, the input's value is driven entirely by React state. Every keystroke calls an onChange handler that updates state, and the state value is fed back into the input as the value prop:
function NameForm() {
const [name, setName] = useState("");
function handleSubmit(event) {
event.preventDefault();
alert(`Submitted: ${name}`);
}
return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
<button type="submit">Submit</button>
</form>
);
}
Because React controls the value, you always have the current input in state and can easily validate, transform, or reset it.
For forms with several fields, use a single state object and update it by field name:
function SignupForm() {
const [fields, setFields] = useState({ email: "", password: "" });
function handleChange(event) {
const { name, value } = event.target;
setFields((prev) => ({ ...prev, [name]: value }));
}
return (
<form>
<input name="email" value={fields.email} onChange={handleChange} />
<input name="password" type="password" value={fields.password} onChange={handleChange} />
</form>
);
}
The computed property [name] updates only the changed field while spreading the rest of the state.
React controls and the same way as text inputs — using a value prop and an onChange handler:
const [colour, setColour] = useState("blue");
<select value={colour} onChange={(e) => setColour(e.target.value)}>
<option value="blue">Blue</option>
<option value="red">Red</option>
</select>
Checkboxes use the checked prop instead of value:
const [agreed, setAgreed] = useState(false);
<input
type="checkbox"
checked={agreed}
onChange={(e) => setAgreed(e.target.checked)}
/>
In an uncontrolled component, you let the DOM manage the input's value and read it using a ref when needed. This is simpler for one-off reads but gives you less control:
import { useRef } from "react";
function UncontrolledForm() {
const inputRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
alert(inputRef.current.value);
}
return (
<form onSubmit={handleSubmit}>
<input ref={inputRef} type="text" defaultValue="" />
<button type="submit">Submit</button>
</form>
);
}
Controlled components are the recommended approach for most forms because they give you full visibility into the form state at every point.
Subscribe to continue reading
Get full access to this lesson and all 10 lessons in this course.