Урок 20. Старый vs Новый: Form против Field
⚡ Кратко
Раньше реестр предлагал компонент Form, жёстко связанный
с react-hook-form. Теперь обвязка полей вынесена в Field
и не зависит от конкретной библиотеки форм.
Обвязка поля
❌ Старый компонент Form
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Почта</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormDescription>Рабочий адрес</FormDescription>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
Работало хорошо, но привязывало разметку к react-hook-form: контекст,
control, рендер-проп на каждое поле.
✅ Field: обвязка отдельно, форма отдельно
<Field data-invalid={!!errors.email}>
<FieldLabel htmlFor="email">Почта</FieldLabel>
<Input id="email" aria-invalid={!!errors.email} {...register("email")} />
<FieldDescription>Рабочий адрес</FieldDescription>
<FieldError errors={[errors.email]} />
</Field>
Разметка одинакова и для react-hook-form, и для нативной формы, и для любой другой библиотеки: обвязка ничего не знает о том, откуда берутся ошибки.
Сравнение
| Признак | Form (старый) | Field (актуальный) |
|---|---|---|
| Зависимость от библиотеки форм | жёсткая | нет |
| Разметка поля | рендер-проп | обычные компоненты |
| Ошибки | FormMessage из контекста | FieldError errors={[…]} |
| Горизонтальные поля | вручную | orientation="horizontal" |
| Группы полей | вручную | FieldSet + FieldLegend |
Если вы поддерживаете проект, где уже используется
старый
Form, — переписывать не обязательно. Но новые формы
удобнее собирать на Field: меньше связанности и проще
тестировать.Валидация: тогда и сейчас
| Что | Тогда | Сейчас |
|---|---|---|
| Правила | атрибуты + ручные проверки в обработчике | схема zod |
| Типы | писались отдельно | z.infer из схемы |
| Сообщения | в JSX рядом с полем | в схеме, рядом с правилом |
| Сервер и клиент | дублирование правил | одна схема на оба конца |