If you've spent some time with React you've probably seen that familiar error message telling you to provide unique keys. This error tends to manifest when iterating over an array of elements in jsx.

Here's what Facebook has to say about the issue:

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:

The best way to pick a key is to use a string that uniquely identifies a list item among its siblings. Most often you would use IDs from your data as keys:

When you don't have stable IDs for rendered items, you may use the item index as a key as a last resort.

Why Is Using index A Last Resort?


const groceries = ["eggs", "ham", "cheese"];

const list = groceries.map((groceries, index) => 
    <li key={index}>{groceries}</li>
);

This is an antipattern because if you push elements into the array or mutate it the data won't display correctly.

Math.random() is Even Worse

Using Math.random() is even worse than using the index for keys.

Math.random() generates a pseudorandom number between 0 and 1. But it will be different for a given element every time the component mounts which causes a huge performance overhead.

The Solution

The solution is to generate static, unique ids for each element.

  • React element keys should be stable; they should not change every time a component mounts or unmounts.
  • React element keys should be unique.

One quick and dirty method is to use the node package react-key-index. You can install the node_module with:

npm install react-key-index --save

react-key-index generated a unique id for each element in an array.

Suppose you have the following array:

var groceries = ["eggs", "ham", "cheese"];

You can generate a unique string for each element as follows:

import keyIndex from 'react-key-index';

var groceries = ["eggs", "ham", "cheese"];

var output = keyIndex(groceries, 1);

The out array will look something like:

[ 
  {
    id: "kwH4H0HgH8HZfV",
    value: "eggs"
  }, {
    id: "5lHRH4HgHzfAc9",
    value: "ham"
  }, {
    id: "X7HGHrHLf8cEf3"
    value: "cheese"
  }
]

An astronomical number of these keys can be generated without sacrificing uniqueness.

You can then use the newly minted IDs in your map function:

output.map((output) => {
  <li key={output._id}>{output.value}</li>
}

What About Objects?

What if you have an array of objects?

Suppose you have an array of objects as follows:


[ 
  { 
    item: "windforce",
    cost: 10000
  }, {
    ...
  }
]

Now calling keyIndex(array, 1) returns:

[
  {
    item: "windforce",
    itemId: "kwH4H0HgH8HZfV",
    cost: 10000,
    costId: "X7HGHrHLf8cEf3"
  }, {
    ... 
  } 
]

In other words, every property of every object in your array gets a unique key.

This is necessary when you need to use map() an array of objects and each jsx element needs a unique key.

Using shortId To Generate Keys

You can also using shortId to generate keys.

Here's an example:

```javascript import shortid from 'shortid';

var arr = ["eggs", "ham", "cheese"];

var arrWithIds = arr.map((arr) => { obj = { _id: shortid.generate(), value: arr }; return obj;

}); });

TL;DR

  • JSX elements need unique, stable keys.
  • Ideally keys should be created when the array is created.
  • Avoid using index or Math.random to generate keys.
  • Use react-key-index or shortId to generate permanent, unique react keys.