reactjsreact-hook-formzod

Zod email validation issue


Issue

I'm working on a React application and wanted to try the newest version of Zod (4.1.13) for input validations along with react hook form. I've been struggling with the z.email() function as it's not displaying the correct message when the user tries to submit the form with no values at all. Instead, the message I always get is the 'Invalid email...' message for that field.

The Zod's documentation (which is not that informative about it) says that you should use the new error property and validate if the input is undefined. i.e.

const LoginSchema = z.object({
  email: z.email({
    error: (issue) =>
      issue.input === undefined
        ? 'Email field is required'
        : 'Invalid email format',
  }),

I tried that but it's still failing, I have no clue about what could be the issue, I tried numerous options to display custom messages, like using the min property, or even use the string function before the email one, but is not allowed to do so in this version. I've heard that some other people may have had the same problem, but couldn't find any useful solution yet.

Attempts to fix the issue:


Solution

  • The Zod's documentation (which is not that informative about it) says that you should use the new error property and validate if the input is undefined

    If you are using Zod alone, yes, this would be sufficient. Keep in mind that the docs share just a single trivial example.

    Given your implementation:

    const LoginSchema = z.object({
      email: z.email({
        error: (issue) =>
          issue.input === undefined
            ? 'Email field is required'
            : 'Invalid email format',
      })
    })
    

    Then LoginSchema.parse({ email: undefined }) would indeed yield the error message "Email field is required". But you are not just working with Zod, you are working with an HTML form and React-Hook-Form and actual form fields.

    In React form field values typically are never undefined as you normally use fully controlled inputs (i.e. the fields always have a defined value provided from outside the input), as is the case when using React-Hook-Form.

    I suspect that issue.value in your case is a string and that you likely want to check that the string is empty instead of checking if it is undefined.

    const LoginSchema = z.object({
      email: z.email({
        error: (issue) =>
          issue.input === "" ? "Email field is required" : "Invalid email format",
      }),
    });
    

    You could also just check for any falsey values as well:

    const LoginSchema = z.object({
      email: z.email({
        error: (issue) =>
          !issue.input ? "Email field is required" : "Invalid email format",
      }),
    });
    
    Email field is required Invalid email format
    Email field is required Invalid email format