Уроки по веб-разработке

Зачем нужен key в React-списках?

Все, кто начинает свою работу с React, думаю, сталкивались с таким warning:

Warning. Each child in a list should have a unique «key» prop.
Предупреждение. Каждый дочерний элемент должен иметь уникальное значение свойства «key»

Эта ошибка может быть не только в списках <li>, но также и в других элементах, которые вы «мапите» из переменной (строки таблицы, изображения, блоки с контентом, видео и т.д.).

Для повышения производительности, отслеживания какие именно элементы изменились в DOM, React нужно, чтобы у них был уникальный ключ.

Так делать не рекомендуется
const Todos = (todos) => {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  )
}

В примере выше, с помощью метода map, мы проходим весь массив todos, который состоит из объектов и на каждой итерации выводим элемент списка с текстом этого таска и задаем уникальный key каждому элементу li.

В методе .map() можно было бы передать второй параметр index — (индекс текущего обрабатываемого элемента в массиве), но так делать не рекомендуется :

const Todos = (todos) => {
  return (
    <ul>
      {todos.map((todo, index) => (
        <li key={index}>{todo.text}</li>
      ))}
    </ul>
  )
}

Всё дело в том, что при изменении порядка расположения элементов в списке, это может вызвать проблемы с производительностью и путаницу в самом компоненте когда вы добавите новые элементы в список или удалите один из существующих.

Лучшим вариантом, в том случае если вы не можете использовать id, будет использование модуля shortid, который сгенерирует уникальный ключ

import shortid from 'shortid';

const Todos = (todos) => {
  return (
    <ul>
      {todos.map(todo => (
        <li key={shortid.generate()}>{todo.text}</li>
      ))}
    </ul>
  )
}

Ключи должны быть уникальными только в пределах элементов одного уровня. Т.е. если у вас несколько списков ul на странице, каждый элемент li должен иметь уникальный атрибут key, только в пределах своего ul