On this Page
On this Guide
- Lesson 13: Validating a User Registration Form
- Lesson 14: Validating API Query Parameters
- Lesson 15: Validating Environment Variables
- Lesson 16: Handling Nested Errors and Formatted Output
- Lesson 17: Reusable Zod Error Parser for Forms
- Lesson 18: Blog Post Editor β Real-World Case Study
- Lesson 19: Zod + React Hook Form Integration
- Lesson 21: Validating Express Requests with Zod
- Lesson 22: Custom Zod Error Formatter for Express APIs
- Lesson 20: Final Thoughts, Best Practices, and Resources
Why Create a Reusable Error Parser?
Zod gives great error information β but every form needs:
- A way to map Zod errors to individual inputs
- A flat structure like:
{ email: "Invalid", password: "Too short" }
Rather than rewrite this logic every time, letβs centralize it π‘
Building the parseZodErrors Utility
import { ZodError } from "zod";
export function parseZodErrors(error: ZodError) {
const formatted: Record<string string> = {};
const issues = error.issues;
for (const issue of issues) {
const path = issue.path.join(".");
if (!formatted[path]) {
formatted[path] = issue.message;
}
}
return formatted;
}
Example Output:
{
"email": "Invalid email address",
"password": "Password must be at least 6 characters"
}
Using It in React Forms
import { parseZodErrors } from "@/utils/parseZodErrors";
const result = RegisterSchema.safeParse(formValues);
if (!result.success) {
const fieldErrors = parseZodErrors(result.error);
setFormErrors(fieldErrors);
}
Now your form can easily display:
{errors.email && <p>{errors.email}</p>}
Advanced: Handling Nested Keys
For nested forms, you’ll still get dotted keys like user.email. You can:
- Leave them as-is for libraries like React Hook Form (supports dot notation)
- Or split them manually for deeply nested custom UIs
fieldErrors["user.email"]; // works if your form inputs use dot notation
> Bonus: You could extend parseZodErrors to support nested objects too, if your UI needs that.
Summary
- Centralize Zod error formatting in a reusable helper
- Map errors to form fields with
issue.path.join(".") - Works with any schema, flat or nested
- Makes frontend integration clean and repeatable
Next: Lesson 18 β Real-World Case Study: Validating a Blog Post Editor
Master the Code, Be the Guru!