Using Index of an array as KEY Can Lead to Bad Consequences

Written by Sujay Prabhu on April 14, 2021; tagged under reactjs

Every application makes use of Lists/arrays in one or the other way. When working with lists in React, one need to be more cautious, because of the key prop which is used with elements within array.

key prop is an identity to an element in the DOM. So, it is expected to be unique and static in order to differentiate between the elements. If you fail to pass key prop, you will end up seeing this in your console .

Warning: Each child in a list should have a unique key prop

At this point, if you think, hey, it's just a warning..., you are taking a chance (PLEASE DON’T). Because this may not seem like causing a serious issue, Believe me, you are not safe either.

Ways of implementing Keys

There are various ways of implementing keys with lists.

1. index of an array

Index as a key is an anti-pattern. This might be the easiest approach to get rid of the warning in the console, but this is a double edged sword. This approach may go wrong, if implemented without proper knowledge.

So, lets have a look at situations in which

In the above code snippet, we have an array and we can add elements either to start/end of the array. If we add elements to end of the array, Item 1 will have key 0 and Item 2 will have key 1. Then, if element is added to start of the array, Item 3 falls on top, but it ends up having key 0 instead of 2.

In order to avoid this unexpected behaviour, we should not use array index as key

{
  list.map((item) => (
    <tr key={item.id}>
      <td>
        <label>{item.id}</label>
      </td>
      <td>
        <input />
      </td>
    </tr>
  ));
}

Now, if the same steps are followed as above, if element is added to the start of the array, Item 3 falls on top and will have key 2

Here is the link of the repository, in which, index is used as key and the other way round for transitions. This demo shows how using index as key will lead to unexpected behaviour.

2. Unique id from dataset

This is undoubtedly the best approach as you have unique id available from the data provided.

const items = [
  {
    id: 1,
    value: 'Item 1',
  },
  {
    id: 2,
    value: 'Item 2',
  },
  {
    id: 3,
    value: 'Item 3',
  },
];

<div>
  {items.map((item) => {
    return <div key={item.id}>{item.value}</div>;
  })}
</div>;

3. Generate unique ids using packages

In situations where you don’t have unique ids along with the list, it is better to generate unique keys with the help of some packages. A lot of packages are available in the internet for generating unique keys/ids like react-uuid, uuid. I am going with react-uuid for now.

import uuid from 'react-uuid';

const arrayWithoutIds = ['user 1', 'user 2', 'user 3'];
const arrayWithIds = arrayWithoutIds.map((element) => {
  return {
    id: uuid(),
    value: element,
  };
});

const Component = ({ arrayWithIds }) => {
  return (
    <div>
      {arrayWithIds.map((item) => {
        return <div key={item.id}>{item.value}</div>;
      })}
    </div>
  );
};

One thing to remember here is, keys should be generated while creating the dataset or before the component mounts (componentWillMount), in order to prevent generation of unique id on every render.

4. Math.Random()

Usage of Math.Random() is not recommended because of its unstability. Because, one cannot deny the possibility of generating the same number twice.

Conclusion:

Happy Learning

If you have any questions or feedback, feel free to drop us a mail at team@codemancers.com.