Forms in React
React uses controlled components where form elements are driven by state.
Controlled Inputs
Bind input values to useState to control them:
function Form() {
const [name, setName] = useState("");
return (
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
);
}
The input always reflects the state value.
Handling Submission
Prevent the default form action and use the state:
function Form() {
const [email, setEmail] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
console.log("Submitted:", email);
};
return (
<form onSubmit={handleSubmit}>
<input value={email} onChange={(e) => setEmail(e.target.value)} />
<button type="submit">Send</button>
</form>
);
}
Multiple Inputs with One Handler
Use the name attribute to handle many fields with a single function:
const [form, setForm] = useState({ name: "", email: "" });
const handleChange = (e) => {
setForm({ ...form, [e.target.name]: e.target.value });
};
<input name="name" value={form.name} onChange={handleChange} />
<input name="email" value={form.email} onChange={handleChange} />
Textarea and Select
These also use value and onChange:
<textarea value={bio} onChange={(e) => setBio(e.target.value)} />
<select value={color} onChange={(e) => setColor(e.target.value)}>
<option value="red">Red</option>
<option value="blue">Blue</option>
</select>
Best Practices
- Always use
valueandonChangefor controlled inputs - Call
e.preventDefault()in the submit handler - Initialize state for every controlled field
Common Mistakes
- Forgetting
e.preventDefault()causes full page reloads - Using
defaultValueinstead ofvaluebreaks control - Not initializing state leads to uncontrolled warnings