Для интеграции Radix UI с React Hook Form необходимо установить обе библиотеки:
npm install @radix-ui/react-dropdown-menu react-hook-form
После установки импортируются необходимые компоненты и хуки:
import { useForm, Controller } from "react-hook-form";
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
useForm предоставляет базовые методы для управления
формой, а Controller используется для интеграции
нестандартных контролов, таких как компоненты Radix UI, которые не
поддерживают стандартные HTML-события onChange и
value.
Radix UI компоненты часто не имеют стандартного API
value/onChange. Для их использования с React Hook Form
применяется Controller:
<Controller
name="fruit"
control={control}
defaultValue=""
render={({ field }) => (
<DropdownMenu.Root>
<DropdownMenu.Trigger>{field.value || "Выберите фрукт"}</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item onSel ect={() => field.onChange("Яблоко")}>Яблоко</DropdownMenu.Item>
<DropdownMenu.Item onSel ect={() => field.onChange("Банан")}>Банан</DropdownMenu.Item>
<DropdownMenu.Item onSel ect={() => field.onChange("Апельсин")}>Апельсин</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
)}
/>
Ключевые моменты:
field.value синхронизирует выбранное значение с
формой.field.onChange используется для обновления состояния
формы при выборе элемента.onSelect заменяет стандартное
onChange.React Hook Form поддерживает встроенную валидацию. Для Radix UI компонентов она реализуется через rules в Controller:
<Controller
name="fruit"
control={control}
rules={{ required: "Выбор фрукта обязателен" }}
render={({ field, fieldState }) => (
<>
<DropdownMenu.Root>
<DropdownMenu.Trigger>{field.value || "Выберите фрукт"}</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item onSel ect={() => field.onChange("Яблоко")}>Яблоко</DropdownMenu.Item>
<DropdownMenu.Item onSel ect={() => field.onChange("Банан")}>Банан</DropdownMenu.Item>
<DropdownMenu.Item onSel ect={() => field.onChange("Апельсин")}>Апельсин</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
{fieldState.error && <span style={{ color: "red" }}>{fieldState.error.message}</span>}
</>
)}
/>
Особенности:
fieldState.error содержит объект ошибки.Radix UI предлагает множество контролов: Slider,
Checkbox, Switch, RadioGroup. Для
каждого применяется Controller для синхронизации с
формой.
Пример: Checkbox
<Controller
name="agree"
control={control}
rules={{ required: "Необходимо согласие" }}
render={({ field }) => (
<>
<Checkbox.Root checked={field.value} onCheckedCha nge={field.onChange}>
<Checkbox.Indicator />
</Checkbox.Root>
{errors.agree && <span>{errors.agree.message}</span>}
</>
)}
/>
Пример: Slider
<Controller
name="volume"
control={control}
defaultValue={50}
render={({ field }) => (
<Slider.Root value={field.value} onValueCha nge={field.onChange}>
<Slider.Track>
<Slider.Range />
</Slider.Track>
<Slider.Thumb />
</Slider.Root>
)}
/>
Особенности:
onValueChange полностью заменяет стандартный
onChange.React Hook Form позволяет динамически добавлять и удалять поля через
useFieldArray. В комбинации с Radix UI это дает
гибкость:
const { fields, append, remove } = useFieldArray({
control,
name: "tasks"
});
fields.map((task, index) => (
<Controller
key={task.id}
name={`tasks.${index}.name`}
control={control}
render={({ field }) => (
<Input value={field.value} onCha nge={field.onChange} />
)}
/>
));
<button type="button" onCl ick={() => append({ name: "" })}>Добавить задачу</button>
Важные моменты:
fields содержит идентификаторы для безопасного рендера
динамических компонентов.append и remove управляют состоянием формы
без перерендера всей формы.useFormState.shouldUnregister: true, чтобы не хранить ненужные поля в
состоянии формы.field.onChange только при изменении
значения.Radix UI поддерживает состояние компонентов через атрибуты:
data-state="open" для Dropdowndata-disabled для элементов, которые неактивныdata-checked для Checkbox и SwitchЭти атрибуты позволяют легко подключать CSS или Tailwind классы для визуализации состояния формы.
[data-state="open"] {
background-color: #f0f0f0;
}
[data-checked] {
border-color: #4f46e5;
}
Radix UI и React Hook Form позволяют строить формы с:
Checkbox
внутри DropdownMenu)Slider с массивом)Комбинация Controller + Radix UI делает форму полностью контролируемой, удобной для валидации и легко масштабируемой.