React 19 Notes
Controlled inputs keep a single source of truth in React state — ideal for validation and reset. React 19 form actions (Server Actions) shine in Next.js; in Vite SPAs, useState remains the standard beginner pattern.
This lesson teaches React forms using controlled components — inputs whose value is driven by React state. You will handle submit events, validate fields, show error messages, and build a complete signup form.
Prerequisites: Lessons 1–5, especially useState. Estimated time: 45–55 minutes.
1. Controlled vs Uncontrolled Inputs
A controlled input stores its value in state and updates via onChange:
const [email, setEmail] = useState('');
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
An uncontrolled input uses a DOM ref — fine for simple cases, but controlled inputs are easier to validate and reset in React apps.

2. Form State as an Object
const [form, setForm] = useState({
name: '',
email: '',
password: '',
});
function handleChange(e) {
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
}
Use the name attribute on each input to update the correct field without separate handlers.

3. Handling Submit
function handleSubmit(e) {
e.preventDefault();
console.log('Submitting', form);
// POST to API or update parent state
}
return (
<form onSubmit={handleSubmit}>
{/* inputs */}
<button type="submit">Sign up</button>
</form>
);
Always call e.preventDefault() unless you want a full page reload.
4. Simple Validation
const [errors, setErrors] = useState({});
function validate() {
const next = {};
if (!form.name.trim()) next.name = 'Name is required';
if (!form.email.includes('@')) next.email = 'Valid email required';
if (form.password.length < 8) next.password = 'Minimum 8 characters';
setErrors(next);
return Object.keys(next).length === 0;
}
function handleSubmit(e) {
e.preventDefault();
if (!validate()) return;
// proceed with valid data
}
Show errors next to fields: {errors.email && <span>{errors.email}</span>}. For larger apps consider React Hook Form or Zod — out of scope for this beginner react forms tutorial.
5. Complete Example — SignupForm
import { useState } from 'react';
function SignupForm() {
const [form, setForm] = useState({ name: '', email: '', password: '' });
const [errors, setErrors] = useState({});
const [submitted, setSubmitted] = useState(false);
function handleChange(e) {
const { name, value } = e.target;
setForm((prev) => ({ ...prev, [name]: value }));
}
function validate() {
const next = {};
if (!form.name.trim()) next.name = 'Name is required';
if (!form.email.includes('@')) next.email = 'Enter a valid email';
if (form.password.length < 8) next.password = 'Use at least 8 characters';
setErrors(next);
return Object.keys(next).length === 0;
}
function handleSubmit(e) {
e.preventDefault();
if (!validate()) return;
setSubmitted(true);
}
if (submitted) {
return <p>Thanks, {form.name}! Check {form.email} to confirm.</p>;
}
return (
<form onSubmit={handleSubmit} style={{ maxWidth: '360px' }}>
<label>
Name
<input name="name" value={form.name} onChange={handleChange} />
{errors.name && <small style={{ color: 'crimson' }}>{errors.name}</small>}
</label>
<label>
Email
<input name="email" type="email" value={form.email} onChange={handleChange} />
{errors.email && <small style={{ color: 'crimson' }}>{errors.email}</small>}
</label>
<label>
Password
<input name="password" type="password" value={form.password} onChange={handleChange} />
{errors.password && <small style={{ color: 'crimson' }}>{errors.password}</small>}
</label>
<button type="submit">Create account</button>
</form>
);
}
export default SignupForm;
Add basic CSS (stack labels with display: block and margin) and test invalid submissions to see validation messages.
6. Checkbox and Select
<input
type="checkbox"
checked={form.agree}
onChange={(e) => setForm((prev) => ({ ...prev, agree: e.target.checked }))}
/>
<select
name="plan"
value={form.plan}
onChange={handleChange}
>
<option value="free">Free</option>
<option value="pro">Pro</option>
</select>
7. Next Steps
Forms capture user input; routing sends users between pages. Next you will add React Router for multi-page navigation in a single-page app.
Series: Lesson 5 · Lesson 7 — React Router
Frequently Asked Questions
What is a controlled component in React?
A controlled component is an input whose value is stored in React state and updated through onChange, giving React full control over the field.
Should I use a form library?
For learning and small forms, plain useState is enough. Libraries like React Hook Form reduce re-renders and simplify validation in large apps.
How do I reset a form after submit?
Call setForm({ name: '', email: '', password: '' }) and setErrors({}) after a successful submit.
Want live React or frontend classes? Join Alkademy for instructor-led React and JavaScript courses with hands-on projects.

Leave a Reply