Что такое контролируемые и неконтролируемые компоненты в React?

👨‍💻 Frontend Developer 🟠 Может встретиться 🎚️ Средний
#React

Краткий ответ

Контролируемые компоненты — React управляет значением элемента формы 💼 Неконтролируемые компоненты — DOM управляет значением элемента формы 🆓

// Контролируемый — значение через state
<input value={value} onChange={handleChange} />
 
// Неконтролируемый — значение напрямую из DOM
<input defaultValue="текст" ref={inputRef} />

Полный ответ

Контролируемые и неконтролируемые компоненты — как разница между управляемой и свободной лошадью! 🐎

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

Контролируемые компоненты — как ручной режим в видеоигре: вы всё контролируете сами:

function ControlledForm() {
  const [name, setName] = useState('');
  
  return (
    <input 
      value={name} 
      onChange={(e) => setName(e.target.value)} 
    />
  );
}

Как это работает:

  1. Значение хранится в состоянии React
  2. При изменении — вызывается обработчик
  3. Обработчик обновляет состояние
  4. Компонент перерисовывается с новым значением

Неконтролируемые компоненты — свобода

Неконтролируемые компоненты — как автопилот: браузер сам управляет, вы только наблюдаете:

function UncontrolledForm() {
  const inputRef = useRef();
  
  return <input defaultValue="начальное значение" ref={inputRef} />;
}

Как это работает:

  1. Значение хранится в DOM элементе
  2. React не контролирует значение
  3. Доступ через ref только когда нужно

Когда что использовать

Контролируемые — для большинства случаев

// ✅ Формы с валидацией
// ✅ Мгновенная проверка
// ✅ Сложные взаимодействия
// ✅ Тестирование
 
<input value={email} onChange={handleEmailChange} />

Неконтролируемые — для простых случаев

// ✅ Простые формы
// ✅ Интеграция с не-React кодом
// ✅ Когда не нужен контроль в реальном времени
 
<input defaultValue={name} ref={nameRef} />

Различия в практике

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

// Полный контроль
const [text, setText] = useState('');
 
// Можно проверять каждый символ
const handleChange = (e) => {
  const value = e.target.value;
  // Проверка: только буквы
  if (/^[a-zA-Z]*$/.test(value)) {
    setText(value);
  }
};
 
<input value={text} onChange={handleChange} />

Неконтролируемые

// Минимум кода
const inputRef = useRef();
 
// Получаем значение только при отправке
const handleSubmit = () => {
  console.log(inputRef.current.value);
};
 
<input defaultValue="текст" ref={inputRef} />

Частые ошибки

Смешивать подходы

// ❌ Ошибка — смешивать value и defaultValue
<input value={name} defaultValue="текст" /> // Конфликт!
 
// ✅ Правильно — выбрать один подход
<input value={name} onChange={handleChange} /> // Контролируемый
// или
<input defaultValue={name} ref={inputRef} /> // Неконтролируемый

Забывать про ref

// ❌ Ошибка — пытаться получить значение неконтролируемого компонента
function Form() {
  // Нет ref!
  return <input defaultValue="текст" />;
  
  // Как получить значение? Никак!
}
 
// ✅ Правильно — использовать ref
function Form() {
  const inputRef = useRef();
  return <input defaultValue="текст" ref={inputRef} />;
}

Простые правила

  1. Контролируемые — значение через state, полный контроль 💼
  2. Неконтролируемые — значение в DOM, свобода 🆓
  3. Контролируемые — для форм с валидацией ✅
  4. Неконтролируемые — для простых случаев 🚀
  5. Не смешивать — выбирать один подход для компонента ⚠️
  6. ref для неконтролируемых — как получить значение 🎯

Понимание разницы между контролируемыми и неконтролируемыми компонентами помогает правильно строить формы в React! 💪


Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪