Выбор ответа Middle Паттерны компонентов спрашивают часто обновлено

Компонент объявлен внутри компонента

Вопрос

При каждом вводе символа поле теряет фокус. Почему?

function Form() {
  const [text, setText] = useState('');

  function Field() {
    return <input value={text} onChange={(e) => setText(e.target.value)} />;
  }

  return <Field />;
}

Попробуйте сами

Выберите вариант, и откроется разбор.

Показать ответ и разбор

Коротко

Правильный ответ: Field объявлен внутри Form: каждый рендер даёт новый тип компонента. React сравнивает тип элемента по ссылке.

Варианты ответа

  1. Field объявлен внутри Form: каждый рендер даёт новый тип компонентаправильный ответ
  2. Не хватает стабильного key у Field, и React путает его с соседним
  3. Нужно обернуть setText в useCallback, иначе Field пересоздаётся
  4. Поле должно быть неконтролируемым, иначе ввод сбрасывает фокус

Разбор

React сравнивает тип элемента по ссылке. Field пересоздаётся при каждом рендере Form, поэтому для React это другой компонент: старый DOM-узел удаляется, создаётся новый, фокус теряется, внутреннее состояние сбрасывается. Объявление Field нужно вынести на верхний уровень модуля.

  • key здесь не поможет: тип всё равно меняется.
  • useCallback для setText не нужен, сеттер и так стабилен, а проблема в типе компонента.
  • Неконтролируемое поле тоже пересоздастся и потеряет фокус.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.