Controlled vs Uncontrolled

В библиотеке Atomico компоненты могут управляться двумя разными подходами: controlled (управляемые) и uncontrolled (неуправляемые). Различие между ними определяется тем, кто отвечает за состояние компонента — внешний код или сам компонент.


Controlled компоненты

Controlled компонент получает своё состояние извне через свойства (props) и уведомляет об изменениях с помощью событий. Вся логика управления состоянием находится в родительском компоненте, что обеспечивает полный контроль над поведением.

import { c, useState } from "atomico";

function TextInput({ value, onChange }) {
    return (
        <input
            value={value}
            onIn put={(event) => onChange(event.target.value)}
        />
    );
}

const App = c(() => {
    const [text, setText] = useState("");

    return <TextInput value={text} onCha nge={setText} />;
});

Ключевые моменты controlled подхода:

  • Состояние хранится снаружи. Компонент не хранит внутреннее состояние, а только отображает текущее значение.
  • Полный контроль над поведением, валидацией и синхронизацией.
  • Предсказуемое поведение: изменение состояния всегда инициируется родителем, что упрощает отладку.
  • Подходит для сложных форм и компонентов, где важна точная синхронизация данных.

Uncontrolled компоненты

Uncontrolled компонент управляет своим состоянием самостоятельно, используя внутренние хуки, такие как useState. Внешний код может только опционально получать уведомления об изменениях, но не управляет состоянием напрямую.

import { c, useState } from "atomico";

function TextInput({ defaultValue, onChange }) {
    const [value, setValue] = useState(defaultValue || "");

    return (
        <input
            value={value}
            onIn put={(event) => {
                setValue(event.target.value);
                onChange?.(event.target.value);
            }}
        />
    );
}

const App = c(() => {
    return <TextInput defaultValue="Привет" />;
});

Особенности uncontrolled компонентов:

  • Состояние локально в компоненте. Родитель не контролирует текущее значение напрямую.
  • Простота использования для независимых элементов.
  • Начальное значение задаётся через defaultValue или аналогичные свойства.
  • Подходит для компонентов, где управление состоянием извне не требуется или может быть редким.

Сравнение подходов

Характеристика Controlled Uncontrolled
Где хранится состояние В родителе В компоненте
Сложность синхронизации Лёгкая, полностью предсказуемая Может быть сложнее при взаимодействии с другими компонентами
Использование хуков useState только в родителе useState внутри компонента
Начальное значение Через value свойства Через defaultValue свойства
Полезно для Форм, сложных UI, синхронизации Независимых элементов, простых полей

Практические рекомендации

  1. Формы и сложные компоненты: использовать controlled подход, чтобы легко валидировать данные и синхронизировать состояние.
  2. Простые поля ввода или виджеты: uncontrolled компоненты позволяют сократить количество кода и избежать лишней синхронизации.
  3. Смешанные сценарии: иногда удобнее сделать компонент uncontrolled, но предоставить опцию value для перехода в controlled режим, что делает компонент гибким и переиспользуемым.
function FlexibleInput({ value, defaultValue, onChange }) {
    const [internalValue, setInternalValue] = useState(defaultValue || "");
    const isControlled = value !== undefined;
    const displayValue = isControlled ? value : internalValue;

    return (
        <input
            value={displayValue}
            onIn put={(event) => {
                if (!isControlled) setInternalValue(event.target.value);
                onChange?.(event.target.value);
            }}
        />
    );
}

Такой подход объединяет преимущества обоих типов: возможность внешнего управления и удобство локального состояния при отсутствии value.


Итоговые нюансы для Atomico

  • Atomico не накладывает строгих ограничений на выбор подхода — оба способа полностью поддерживаются.
  • Управление через props и события (onInput, onChange) соответствует стандартной модели DOM и React-подобным библиотекам.
  • Для крупных приложений controlled компоненты обеспечивают более безопасную архитектуру, но uncontrolled компоненты остаются полезными для простых элементов.

Controlled и uncontrolled подходы в Atomico — это инструмент для гибкой архитектуры компонентов, позволяющий выбирать между полной внешней синхронизацией и автономностью.