React key error

Learn what is the root cause, and how to fix 'Warning: Each child in a list should have a unique 'key' prop.' warnings in your React app.

The «Each child in a list should have a unique «key» prop.» warning happens in React when you create a list of elements without the special key attribute. Keys must be assigned to each element in a loop to give stable identity to elements in React.

// ❌ Invalid, will cause the above error due to missing "key" prop
{posts.map(post => <Post details={post} />)}

// ✔️ Each element now has a unique key
{posts.map(post => <Post details={post} key={post.id} />)}

// ✔️ You can also use the index of the array
{posts.map((post, index) => <Post details={post} key={index} />)}

Copied to clipboard!

The key is used to correctly link the component to the DOM element. Keys must also be unique across siblings. The most common way to use unique IDs is to use either an id property on the passed object or use the index of the array.

Avoid using Math.random as the key for a component, as it doesn’t provide unique values, and duplicate keys can occur.

// ❌ Don't use Math.random for a key
{posts.map(post => <Post details={post} key={Math.random()} />)}

Copied to clipboard!

Keys only need to be unique among siblings. They don’t need to be unique globally.

After the warning, you will also see a line mentioning to «Check the render method of `Component`.». This way, you will know exactly which component is causing the error, and where to look for the bug.

Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.

Master JavaScript


When Should You Not Use Array Indexes for Keys

Using array indexes for keys is a great way to give each element in a list a unique key if you don’t have an id property on your data. However, if the order of the elements can be changed, this can cause issues in React.

Think of adding, removing, reordering, or filtering elements, such as when working with filters. In order to have unique key props for reordered elements, you must use a unique ID from your data. In case you don’t have IDs on your data available, you can also use the uuid NPM package to generate unique IDs for your elements.

// ❌ This will not work if the array can be sorted or filtered
{posts.map((post, index) => <Post details={post} key={index} />)}

// ✔️ You must use a unqie ID in this case
{posts.map(post => <Post details={post} key={post.id} />)}

// ✔️ You can also use the uuid package
import { v4 } from 'uuid'

{posts.map(post => <Post details={post} key={v4()} />)}

Copied to clipboard!

Table of Contents
Hide
    1. What is a key prop?
    2. Why is it required?
    3. But why React asks for keys only on list?
    4. Some good keys to use
  1. Related Posts

React throws error, each child in a list should have a unique “key” prop when you do not provide key prop in the list item. Let’s understand what this is and why it is required.

What is a key prop?

When we create a list using map or forEach function, we ask react to render a collection of JSX. This list could be html list of ul and li or it can be any kind of JSX. Generally, list items are of similar structure but different data. React expect us to provide a unique key to each item of the list. We use key prop for that. Its syntax is –

someArray.map(item => {
  return <div key={'uniqueValue'}></div>
})

Why is it required?

According to React manual –

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.

There are many operations on websites which are costly in terms of performance. One of these are DOM manipulation. React is fast because it tries to manipulate DOM only when it is necessary. So, if there is a new element to be shown on webpage then React tries not to re-render everything but just the new element.

But why React asks for keys only on list?

Because generally list items are huge in number. Another reason is that when you add or remove items from the list, it is best to render only that item on the DOM and others remain as they were. This can only be possible when React knows what is added and where. Let’s understand this with examples –

Suppose, you have a list –

<ul>
  <li>Captain America</li>
  <li>Ironman</li>
</ul>

React will render this list. Now we add one item at last index –

<ul>
  <li>Captain America</li>
  <li>Ironman</li>
  <li>Thor</li>
</ul>

Here, react will check the new list tree with the old one. It will compare the first list item of old subtree with new subtree – Captain America, which is unchanged. So, no DOM manipulation will be done.

Similarly, Ironman is not changed. But Thor is added so one DOM manipulation is needed for Thor.

But, if you add a list item at the beginning then it will unnecessarily re-render all 3 items.

<ul>
  <li>Thor</li>
  <li>Captain America</li>
  <li>Ironman</li>
</ul>

Here,

  • Captain America will be matched against Thor,
  • Ironman against Captain America and
  • Thor against Ironman.

Nothing will match and hence everything will be re-rendered, even though the 2 items are same. If the list is small, this is not a problem but when it is large, you can visually see the performance lag.

To solve this issue, React asks the users to provide a unique key to all items rendered through loops like map() or forEach(). You may use anything as key as long as they are unique to each other and same for a list item.

So, instead of using the element to match each other, React will use keys to check if an element with that key exists on the DOM. For example –

<ul>
  <li key={'captain_america'}>Captain America</li>
  <li key={'ironman'}>Ironman</li>
</ul>

Now if you add Thor anywhere in the list, it will not affect the rendering of any other list item because react knows that 'captain_america' key existed in the previous render and so DOM already has the element.

But if you changed the element and didn’t update the key, then the change will not be reflected on DOM. For example –

<ul>
  <li key={'captain_america'}>Captain America - First Avenger</li>
  <li key={'ironman'}>Ironman</li>
</ul>

    Tweet this to help others

Dom will keep on showing Captain America and not Captain America - First Avenger. You need to change the key 'captain_america' to something else like 'captain_america_FA'.

Math.Random() is a bad choice for keys because although it remains unique among list items, it will also generate a new random number on every render which will force react to re-render all elements. So basically it will be useless.

Some good keys to use

  • A primary key id provided by database.
  • Hash of item’s value.

We should try not to use array indexes as keys because they are not stable. When you add an item to array, other items will change position and hence their keys will change. This will result in unexpected outcome.

Because of these reasons, React warns you about each child in a list should have a unique key props.

This is Akash Mittal, an overall computer scientist. He is in software development from more than 10 years and worked on technologies like ReactJS, React Native, Php, JS, Golang, Java, Android etc. Being a die hard animal lover is the only trait, he is proud of.

Related Tags
  • Error,
  • react js short,
  • reactjs error

Все, кто начинает свою работу с 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

Ваши вопросы и комментарии:

Понравилась статья? Поделить с друзьями:
  • React hook form error message
  • React fetch error handling
  • React fetch cors error
  • React fetch catch error
  • React error page