在 NextJs14 和服务器操作中使用表单时,尝试在客户端和服务器端实现 Zod 验证。 当在 RHF
onSubmit
挂钩中将模式设置为 useForm
(这是默认模式)时,按下提交按钮时不会触发客户端验证。直接进入服务器端验证(有效)。
但是,当将模式更改为 onChange
或 onBlur
时,验证工作正常。
值得一提的是,useForm
钩子也提供了isValid布尔值,在提交之前是
False
,这意味着Zod正在做的是Job。但错误对象是空的,因此无法向用户显示 pb。
有人遇到同样的问题吗
"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 };
架构
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>;
看起来您没有使用react-hook-forms提供的onSubmit处理程序
const { register, handleSubmit } = useForm();
也许尝试一下如何将 handleSubmit 包裹在操作上并尝试?