Формы и controlled inputs

Связываем поля ввода с состоянием так, что React становится единственным источником правды о форме.

Управляемый компонент (controlled input) — поле, значение которого хранится в состоянии React и задаётся через value, а меняется через onChange.

Идея: состояние — источник правды

Обычное HTML-поле само хранит свой текст. В React предпочитают, чтобы значение жило в состоянии: так его легко прочитать, проверить, очистить. Связка из двух частей:

  • value={text} — поле всегда показывает значение из состояния;
  • onChange — при вводе записывает новое значение в состояние.
function NameInput() {
  const [name, setName] = useState("");

  return (
    <div>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      <p>Привет, {name || "незнакомец"}!</p>
    </div>
  );
}

Получается цикл: пользователь печатает → onChange обновляет состояние → React перерисовывает → поле показывает новое value. Состояние и поле всегда синхронны.

Почему именно так

Раз значение в состоянии, вы в любой момент можете им управлять: подставить значение по умолчанию, очистить поле (setName("")), запретить определённые символы, показать ошибку. С неуправляемым полем это сделать гораздо сложнее.

Несколько полей — один объект

Для формы с многими полями держат состояние объектом и обновляют его иммутабельно по имени поля:

function SignupForm() {
  const [form, setForm] = useState({ email: "", password: "" });

  function handleChange(e) {
    const { name, value } = e.target;
    setForm((prev) => ({ ...prev, [name]: value }));
  }

  return (
    <form>
      <input name="email" value={form.email} onChange={handleChange} />
      <input name="password" value={form.password} onChange={handleChange} />
    </form>
  );
}

Один обработчик обслуживает все поля: по e.target.name он понимает, какое поле менять, а [name]: value (вычисляемое имя свойства) обновляет нужный ключ.

Чекбоксы: checked вместо value

У чекбокса состояние булево, и связывают его через checked и e.target.checked:

function Agree() {
  const [agree, setAgree] = useState(false);
  return (
    <label>
      <input
        type="checkbox"
        checked={agree}
        onChange={(e) => setAgree(e.target.checked)}
      />
      Согласен с условиями
    </label>
  );
}

Памятка по полям

ПолеЧто связыватьЧто читать
text / textareavaluee.target.value
checkboxcheckede.target.checked
selectvaluee.target.value

Итог

  • Управляемое поле: value из состояния + onChange, записывающий e.target.value обратно.
  • Для многих полей держат объект и обновляют ключ через [name]: value.
  • У чекбокса используют checked и e.target.checked вместо value.
Проверьте себя
1. Что делает поле «управляемым» (controlled) в React?
AНаличие атрибута name
BЕго значение хранится в состоянии и задаётся через value, а меняется через onChange
CИспользование тега <form>
DАтрибут disabled
2. Как одним обработчиком обновлять нужное поле в объекте-состоянии формы?
AsetForm(value)
BsetForm(prev => ({ ...prev, [e.target.name]: e.target.value }))
Cform[name] = value
DsetForm({ name: value })
3. Что используют для связывания состояния с чекбоксом?
Avalue и e.target.value
Bchecked и e.target.checked
Cselected и e.target.selected
Don и e.target.on
Поддержать проект