Craig Glennie

Debugging validation issues between react-hook-form and zod

When using react-hook-form with zod via zodResolver you might run into a problem where your form won’t validate and you don’t know why - no error is thrown, no log messages written, but formState.isValid never shows true.

Here’s the tip: If you are using defaultValues with useForm then your zod schema needs to be able to validate defaultValues. If it fails to validate then you won’t know why, your form will just stay invalid. But you can test in your code:

const {
    handleSubmit,
    control,
    formState: { isDirty, isValid, errors },
  } = useForm({
    defaultValues,
    resolver: zodResolver(zFormSchema),
    mode: "onBlur",
  });

// Directly parse defaultValues to surface a parsing error. 
// I recommend leaving this in the code, that way if the schema
// and defaultValues diverge you will know right away 
// (a softer alternative is to use safeParse and log the issue,
// but then your form is probably silently broken)
  zFormSchema.parse(defaultValues);

This doesn’t cover every possibility (eg if you’re doing something custom with .transform then your defaultValues might not hit it) but in general defaultValues is coming from your DB, so is presumed to be valid. This has helped me debug a few validation issues with react-hook-form and zod.