Ответ вслух Junior Код-ревью спрашивают часто обновлено

Ревью: список с удалением

Вопрос

Перед тобой код на ревью. Скажи вслух, что здесь не так - по убыванию важности.

Читай вслух, как на ревью: сначала что делает код, потом что сломано.

function TodoList({ todos, onRemove }) {
  return (
    <ul>
      {todos.map((todo, i) => (
        <li key={i}>
          <input defaultValue={todo.text} />
          <button onClick={() => onRemove(i)}>×</button>
        </li>
      ))}
    </ul>
  );
}

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

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

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

Коротко

Ключ по индексу плюс неконтролируемое поле - классическая пара, дающая самый неприятный баг. Удаляем второй элемент: React видит те же ключи 0,1,2 у другого набора данных, переиспользует существующие узлы - и текст, введённый в третье поле, оказывается во втором.

Что должно прозвучать в ответе

  • key по индексу - при удалении состояние полей съезжает на соседние

  • нужен стабильный key из данных - todo.id

  • defaultValue делает поле неконтролируемым, изменения никуда не сохраняются

  • onRemove принимает индекс, а не идентификатор - ломается при сортировке и фильтрации

  • у кнопки нет доступного имени - символ × скринридер не прочитает

  • нет обработки пустого списка

Что могут спросить следом

  • Когда key по индексу всё-таки допустим?
  • Как сохранять правку - по каждому нажатию или по blur?

Разбор

Ключ по индексу плюс неконтролируемое поле - классическая пара, дающая самый неприятный баг. Удаляем второй элемент: React видит те же ключи 0,1,2 у другого набора данных, переиспользует существующие узлы - и текст, введённый в третье поле, оказывается во втором. Нужен key={todo.id}.

defaultValue означает, что значение живёт в DOM и никуда не сохраняется: пользователь отредактировал задачу, ушёл со страницы - правка потеряна. Либо контролируемое поле с onChange, либо сохранение по onBlur.

Индекс в колбэке. onRemove(i) привяжет удаление к позиции: после сортировки или фильтрации удалится не то. Передавать нужно todo.id.

Доступность: <button aria-label="Удалить задачу"> - «×» скринридер прочитает как «знак умножения» или промолчит.

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

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