Zod resolver's refinement doesn't run with the rest of validation #8516
-
Hello all, I am using react-hook-form along with Zod and I have some refinement issues - specifically, some errors that should arise on refinement do not come up unless the rest of the fields (that do not refinement) have had correct input. Codesandbox: https://codesandbox.io/s/stupefied-leavitt-r97xcz If you run the sandbox and press the Submit button, you will see that all fields produce some errors except the "country" field. My Zod schema has a super refine where I place some explicit checks on whether the user has selected a country. Unfortunately, the errors that it produces appear on screen only when all the other fields have been filled up correctly according to the schema requirements. Is there a way to have the refinement error appear simultaneously along with the rest of the errors on the other fields? Thank you very much in advance. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 2 replies
-
I need helpo with this too. Were you able to figure it out? |
Beta Was this translation helpful? Give feedback.
-
Related #8809 |
Beta Was this translation helpful? Give feedback.
-
Actually, this is still a problem in 2024. // Let's define your resolver
const isUrl =
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/
export const myCustomSchema: ZodType<PostForm> = z
.object({
videoUrl: z
.string()
.refine((videoUrl) => {
if (
videoUrl.length > 0 &&
isUrl.test(videoUrl)
)
return false
return true
}, "must_be_valid_youtube_url")
.optional(),
message: z
.string()
.refine((message) => {
if (message.length > 0 && isUrl.test(message)) return false
return true
}, "no_url_in_message")
.optional()
})
.partial()
// Destructure our react-hook-form
const {
register,
handleSubmit,
formState,
watch, // < add this
trigger // < add this
} = useForm<PostForm>({
resolver: zodResolver(myCustomSchema)
})
React.useEffect(() => {
const subscription = watch(() => {
trigger(["message", "videoUrl"])
})
return () => subscription.unsubscribe()
}, [watch, trigger])
// Then in your JSX:
{formState.errors?.videoUrl && (
<span className="text-red-700">
{translate(
`posts.${formState.errors.videoUrl.message}`,
lang
)}
</span>
)}
{formState.errors?.message && (
<span className="text-red-700">
{translate(
`posts.${formState.errors.message.message}`,
lang
)}
</span>
)} |
Beta Was this translation helpful? Give feedback.
Related #8809