On this page
Forms in React
React forms use controlled components — form state is managed by React state.
Controlled Input
function NameInput() {
const [name, setName] = useState('');
return (
<div>
<input
value={name}
onChange={e => setName(e.target.value)}
placeholder="Enter name"
/>
<p>Hello, {name || 'stranger'}!</p>
</div>
);
}
Multiple Inputs
function ContactForm() {
const [form, setForm] = useState({
name: '',
email: '',
message: ''
});
const handleChange = (e) => {
const { name, value } = e.target;
setForm(prev => ({ ...prev, [name]: value }));
};
const handleSubmit = (e) => {
e.preventDefault();
console.log(form);
};
return (
<form onSubmit={handleSubmit}>
<input name="name" value={form.name} onChange={handleChange} />
<input name="email" type="email" value={form.email} onChange={handleChange} />
<textarea name="message" value={form.message} onChange={handleChange} />
<button type="submit">Send</button>
</form>
);
}
Select and Checkbox
function Preferences() {
const [country, setCountry] = useState('us');
const [newsletter, setNewsletter] = useState(false);
return (
<div>
<select value={country} onChange={e => setCountry(e.target.value)}>
<option value="us">United States</option>
<option value="uk">United Kingdom</option>
<option value="ca">Canada</option>
</select>
<label>
<input
type="checkbox"
checked={newsletter}
onChange={e => setNewsletter(e.target.checked)}
/>
Subscribe to newsletter
</label>
</div>
);
}
Form Validation
function SignupForm() {
const [email, setEmail] = useState('');
const [errors, setErrors] = useState({});
const validate = () => {
const newErrors = {};
if (!email) newErrors.email = 'Email is required';
else if (!/\S+@\S+\.\S+/.test(email)) newErrors.email = 'Invalid email';
return newErrors;
};
const handleSubmit = (e) => {
e.preventDefault();
const newErrors = validate();
if (Object.keys(newErrors).length > 0) {
setErrors(newErrors);
return;
}
setErrors({});
// Submit form...
};
return (
<form onSubmit={handleSubmit}>
<input
value={email}
onChange={e => setEmail(e.target.value)}
className={errors.email ? 'error' : ''}
/>
{errors.email && <span className="error-msg">{errors.email}</span>}
<button type="submit">Sign Up</button>
</form>
);
}
Uncontrolled Components
Use useRef when you don’t need live state updates:
import { useRef } from 'react';
function QuickForm() {
const inputRef = useRef(null);
const handleSubmit = (e) => {
e.preventDefault();
console.log(inputRef.current.value);
};
return (
<form onSubmit={handleSubmit}>
<input ref={inputRef} defaultValue="" />
<button type="submit">Submit</button>
</form>
);
}
Prefer controlled components for most forms — they give you full control over validation and UI feedback.