Reputation: 2761
Trying to implement Zod validation on both Client and server side, when using forms in NextJs14 and server actions.
When setting mode to onSubmit
(which is the default mode) in the RHF useForm
hook, the client side validation is not triggered when pressing the submit button. Directly goes to the server side validation (that works).
However, when changing the mode to onChange
or onBlur
, the validation is working fine.
It's worth to mention that the isValid boolean, also provided by the useForm
hooks is False
before submitting which means that Zod is doing is Job. But the errors objects is empty, so can not displayed the pb to the users.
Does anyone got the same issue ?
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { FC, useEffect } from "react";
import { useFormState, useFormStatus } from "react-dom";
import {
FieldErrors,
FieldPath,
UseFormRegister,
useForm,
} from "react-hook-form";
import InputField from "./InputField/InputField";
import { TestFormState, getFullName } from "./testAction";
import { TTestForm, formSchema } from "./validationTestForm";
type ITestFormProps = {};
export type FormValues = TTestForm;
export function FormContent({
register,
isValid,
errors,
}: {
register: UseFormRegister<FormValues>;
isValid: boolean;
errors: FieldErrors<FormValues>;
}) {
const { pending } = useFormStatus();
return (
<>
<div className="flex items-center justify-start">
<input {...register("firstName")} placeholder="First name" />
</div>
<div className="flex items-center justify-start">
<input {...register("lastName")} placeholder="Last name" />
</div>
<button type="submit" disabled={pending}>
Send
</button>
<div>{pending && <span>Loading...</span>}</div>
<div>{`${errors} - ${isValid}`}</div>
</>
);
}
const TestForm: FC<ITestFormProps> = (_props: ITestFormProps): JSX.Element => {
const {
register,
formState: { isValid, errors },
setError,
reset,
} = useForm<FormValues>({
resolver: zodResolver(formSchema),
criteriaMode: "all",
mode:"onSubmit" // <-- "isValid" is correct but not "errors". Changing to onBlur fix the issue
});
const [state, formAction] = useFormState<TestFormState, FormData>(
getFullName,
null
);
return (
<>
<form action={formAction}>
<FormContent register={register} isValid={isValid} errors={errors} />
</form>
<>{state && JSON.stringify(state)}</>
</>
);
};
export default TestForm;
export type { ITestFormProps };
schema
export const formSchema = zfd.formData({
firstName: zfd.text(z.string().min(2, "Too short").max(20, "Too long")),
lastName: zfd.text(
z.string().min(2, "Too short").max(20, "Too long").optional()
)
});
export type TTestForm = z.infer<typeof formSchema>;
Upvotes: 0
Views: 452
Reputation: 1
That looks like you are not using the onSubmit handler provided by react-hook-forms
const { register, handleSubmit } = useForm();
Maybe try playing around with how you can wrap the handleSubmit around the action and try?
Upvotes: 0