Программное управление

Radix UI предоставляет низкоуровневые, полностью контролируемые компоненты пользовательского интерфейса, которые можно интегрировать в любые React-приложения. Основной принцип программного управления заключается в том, что состояние компонентов можно контролировать извне с помощью пропсов и колбеков, что обеспечивает гибкость и предсказуемость поведения интерфейса.


Контролируемые и неконтролируемые компоненты

Неконтролируемые компоненты управляют своим внутренним состоянием самостоятельно. Например, Accordion или Dialog могут открываться и закрываться по внутренней логике, без вмешательства извне:

<Dialog>
  <DialogTrigger>Открыть диалог</DialogTrigger>
  <DialogContent>Содержимое диалога</DialogContent>
</Dialog>

Контролируемые компоненты позволяют управлять состоянием извне через пропсы, обычно это open, value или checked, а также через обработчики событий onOpenChange, onValueChange и т.д. Это особенно важно при интеграции компонентов с глобальным состоянием, формами или логикой бизнес-процессов.

Пример контролируемого диалога:

const [isOpen, setIsOpen] = React.useState(false);

<Dialog open={isOpen} onOpenCha nge={setIsOpen}>
  <DialogTrigger>Открыть диалог</DialogTrigger>
  <DialogContent>Содержимое диалога</DialogContent>
</Dialog>

Здесь isOpen полностью контролирует видимость диалога, а setIsOpen синхронизирует состояние с внешней логикой.


Управление сложными состояниями

Radix UI компоненты поддерживают композицию состояния через пропсы value, defaultValue и соответствующие колбеки. Например, Tabs можно сделать полностью управляемыми:

const [activeTab, setActiveTab] = React.useState('tab1');

<Tabs value={activeTab} onValueCha nge={setActiveTab}>
  <TabsList>
    <TabsTrigger value="tab1">Вкладка 1</TabsTrigger>
    <TabsTrigger value="tab2">Вкладка 2</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">Контент вкладки 1</TabsContent>
  <TabsContent value="tab2">Контент вкладки 2</TabsContent>
</Tabs>

Такое программное управление позволяет синхронизировать состояние вкладок с URL, глобальным стором (Redux, Zustand, Recoil) или другими компонентами интерфейса.


Использование рефов и методов API

Radix UI предоставляет рефы к DOM-элементам и иногда expose-методы через ref или imperativeHandle, что позволяет выполнять действия программно, не завися от пользовательских событий.

Пример программного открытия диалога через реф:

const dialogRef = React.useRef(null);

<Dialog ref={dialogRef}>
  <DialogTrigger>Открыть диалог</DialogTrigger>
  <DialogContent>Содержимое</DialogContent>
</Dialog>

<button onCl ick={() => dialogRef.current?.show()}>Открыть программно</button>

Не все компоненты поддерживают прямой доступ к методам через реф, но большинство предоставляет необходимые колбеки для полного контроля состояния.


Связь с формами и внешним состоянием

Компоненты Radix UI отлично интегрируются с React Hook Form и другими библиотеками для управления формами. Для этого используется программное управление значениями и событиями:

const { control } = useForm();

<Controller
  control={control}
  name="switchValue"
  render={({ field }) => (
    <Switch
      checked={field.value}
      onCheckedCha nge={field.onChange}
    />
  )}
/>

Здесь Switch становится полностью управляемым, а его состояние синхронизировано с формой.


Синхронизация между несколькими компонентами

Программное управление позволяет синхронизировать несколько компонентов между собой. Например, один Slider может управлять значением Progress:

const [value, setValue] = React.useState(50);

<Slider value={value} onValueCha nge={setValue} />
<Progress value={value} />

Изменение слайдера мгновенно обновляет прогресс-бар, без использования сторонних библиотек для связывания состояния.


Дебаунс и оптимизация обновлений

Для больших приложений важно избегать лишних рендеров при программном управлении. Использование React.useCallback и мемоизация значений помогает снизить нагрузку:

const handleChange = React.useCallback((val) => {
  setValue(val);
}, []);

<Slider value={value} onValueCha nge={handleChange} />

Программное управление анимациями и поведением

Radix UI часто предоставляет анимированные компоненты, например Accordion или Collapsible. Управление открытием/закрытием программно позволяет синхронизировать анимацию с другими событиями приложения:

const [isOpen, setIsOpen] = React.useState(false);

<Collapsible open={isOpen} onOpenCha nge={setIsOpen}>
  <CollapsibleTrigger>Toggle</CollapsibleTrigger>
  <CollapsibleContent>Контент</CollapsibleContent>
</Collapsible>

<button onCl ick={() => setIsOpen((prev) => !prev)}>Программный toggle</button>

В этом примере анимация раскрытия полностью подчинена внешнему состоянию.


Программное управление в Radix UI открывает возможности гибкого интегрирования компонентов в сложные React-приложения, синхронизации с глобальным состоянием, формами и внешней логикой, при этом сохраняя полный контроль над поведением интерфейса и минимизируя непредсказуемые побочные эффекты.