Ревью: список с удалением
Вопрос
Перед тобой код на ревью. Скажи вслух, что здесь не так - по убыванию важности.
Читай вслух, как на ревью: сначала что делает код, потом что сломано.
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 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
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 ошибок.