Module 35: Forms and Validation in React
Form state
🏠The everyday picture
A clerk filling in a form for you keeps all the answers on one sheet, not on separate scraps of paper, so nothing is lost and the whole form can be checked at once.
📘What it really is
- For a form with several fields, keep the values together in one state object:
type EnquiryForm = { name: string; email: string; subject: string; message: string };
const empty: EnquiryForm = { name: "", email: "", subject: "", message: "" };
const [form, setForm] = useState<EnquiryForm>(empty);
function handleChange(event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) {
const { name, value } = event.target;
setForm(f => ({ ...f, [name]: value }));
}
[name]: valueuses the input'snameattribute to update the right field, so one handler serves every input.- Submitting:
function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
event.preventDefault();
// check, then use form
}
<form onSubmit={handleSubmit} noValidate>...</form>
preventDefault stops the browser reloading the page (Module 19). noValidate turns off the browser's own
pop-up messages, because you'll show your own, more helpful ones (keep attributes like required and
type="email", which still help assistive technology and phone keyboards).
- After a successful submit, reset with
setForm(empty).
🖱️Try it
Create pages/NewEnquiry.tsx with a form for name, email, subject and message, using one state object and one
change handler. On submit, add a new enquiry (with a new id, status "new", and createdAt set to now) to the
dashboard's list, and clear the form. Show the form above the lists for now.
✅Quick check
What does [name]: value do in setForm(f => ({ ...f, [name]: value }))?
Show the answer
It updates the field whose name matches the input's name attribute, keeping all other fields.
Why call event.preventDefault() in a React form's submit handler?
Show the answer
To stop the browser's default full-page reload, so React handles the submission.
