У меня возникли проблемы с отображением ошибки проверки zod в FormMessage. Я следил за документацией shadcn по форме и вводу и делал все то же самое, но не могу понять, почему это не работает.
У меня есть этот компонент ввода формы (сделано так, чтобы его можно было использовать повторно)
export const FormInput = <T extends FieldValues>(
props: FormElementProps<T>
) => {
return (
<FormField
control = {props.form.control}
name = {props.name}
render = {({ field }) => (
<FormItem>
{props.label && <FormLabel>{props.label}</FormLabel>}
<FormControl>
<Input
{...field}
type = {props.type}
disabled = {props.disabled}
placeholder = {props.placeholder}
/>
</FormControl>
{props.description && (
<FormDescription>{props.description}</FormDescription>
)}
<FormMessage />
</FormItem>
)}
/>
);
};
Схема зода следующая
export const loginViewFormSchema = z.object({
email: z.string().email({ message: "Email is required" }),
password: z.string().min(1, {
message: "Password is required",
}),
});
const loginForm = useForm<z.infer<typeof loginViewFormSchema>>({
resolver: zodResolver(loginViewFormSchema),
defaultValues: {
email: "",
password: "",
},
});
И форма используется вот так
<Form {...props.form}>
<form
onSubmit = {handleSubmit(formSubmitHandler)}
className = "flex flex-col space-y-2"
>
<FormInput
form = {props.form}
label = "Email"
name = "email"
disabled = {formState.isSubmitting}
/>
<FormInput
form = {props.form}
label = "Password"
name = "password"
type = "password"
disabled = {formState.isSubmitting}
/>
<Button type = "submit" disabled = {formState.isSubmitting}>
{formState.isSubmitting && (
<Icons.spinner className = "w-4 h-4 mr-2 animate-spin" />
)}
Sign In
</Button>
<Button type = "button" variant = "link" onClick = {onClickForgotPassword}>
Having trouble signing in?
</Button>
</form>
</Form>
Под каждым вводом должны отображаться ошибки проверки, если значения не такие, как они должны быть основаны на схеме zod, но ничего не происходит.
Вот ссылка на песочницу кода, которая воспроизводит проблемы. https://codesandbox.io/p/devbox/sharp-jasper-z6c4gz?file=%2Fapp%2Fpage.tsx%3A15%2C6
Я попробовал переустановить пакеты реакции-хука-формы и zod и понизить версию, но ничего не помогло. Я видел, что ошибки формы соответствуют ожиданиям в определении схемы, но сообщение об ошибке не передается в FormMessage из компонента FormInput.
Вот решение вашей проблемы. Вы делаете что-то не так, если уместно использовать это слово.
Почему вы разрушаете форму и состояние формы, это выглядит ненужным и повторяющимся. Вы разрушаете его, чтобы создать новый объект, разве состояние формы уже не является объектом. formState уже существует как объект внутри объекта формы.
form = {{
...loginForm,
formState: {
...loginForm.formState,
isSubmitting: loginForm.formState.isSubmitting,
},
}}
Я заменил это на это
form = {loginForm}
Вот и все. Вы можете найти мое решение здесь, на codeandbox. https://codesandbox.io/p/devbox/sharp-jasper-forked-9dksfm
вы не используете это правильно:
const loginForm = useForm<z.infer<typeof loginViewFormSchema>>({
resolver: zodResolver(loginViewFormSchema),
defaultValues: {
email: "",
password: "",
},
});
вы передаете loginForm
каждому компоненту FormInput
как props
. это тоже имеет свойство errors
. в вашем компоненте FormInput
:
export const FormInput = <T extends FieldValues>(
props: FormElementProps<T>,
) => {
return (
<FormField
control = {props.form.control}
name = {props.name}
render = {({ field }) => (
<FormItem>
{props.label && <FormLabel>{props.label}</FormLabel>}
<FormControl>
<Input
{...field}
type = {props.type}
disabled = {props.disabled}
placeholder = {props.placeholder}
/>
</FormControl>
{props.description && (
<FormDescription>{props.description}</FormDescription>
)}
<FormMessage />
</FormItem>
)}
/>
);
};
FormInput.displayName = "FormInput";
тебе стоит добавить это в FormInput
{props.error && <span>{error.message}</span>}