Module 35: Forms and Validation in React
Validation rules
🏠The everyday picture
A checklist the clerk runs through before accepting a form: name present, email looks right, message long enough. The same checklist every time, written down once.
📘What it really is
- Write validation as a pure function that returns errors per field (Module 23):
type Errors = Partial<Record<keyof EnquiryForm, string>>;
function validate(form: EnquiryForm): Errors {
const errors: Errors = {};
if (!form.name.trim()) errors.name = "Please enter your name.";
if (!/^\S+@\S+\.\S+$/.test(form.email)) errors.email = "Please enter an email like name@example.com.";
if (form.message.trim().length < 10) errors.message = "Please write at least 10 characters.";
return errors;
}
-
keyof EnquiryFormmeans "one of the form's field names", so errors can only be set for real fields (Module 29's utility types). -
The form is valid when
Object.keys(errors).length === 0. - Being pure,
validateis easy to test withnode --testor Vitest (Module 39). -
Schema libraries such as Zod describe the rules once and give you both validation and TypeScript types. They're common in real projects, and the same schema can be used on the server (Module 43). Learn the idea by hand first.
-
Remember: frontend validation helps people; the server must validate again (Module 13).
🖱️Try it
Write validate in src/validation.ts. Add rules: subject between 3 and 100 characters; message at most 2,000
characters. Write at least six tests for it, including spaces-only input and a long message.
✅Quick check
Why write validation as a separate pure function?
Show the answer
It can be tested on its own, reused, and keeps the component simpler.
Your React form validates perfectly. Does the server still need to check?
Show the answer
Yes. Requests can be sent without your form; the server must always validate.
