If you've spent some time with React you've probably seen that familiar error message telling you to provide unique keys. <!-- more --> 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 <code>index</code> 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.

<code>Math.random()</code> is Even Worse

Using <code>Math.random()</code> is even worse than using the index for keys.

<code>Math.random()</code> 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 <code>react-key-index</code>. You can install the <a href="">node_module</a> with:

npm install react-key-index --save

<code>react-key-index</code> 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 <code>out</code> 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
  }, {
    ...
  }
]

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.

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 <code>react-key-index</code> or <code>shortId</code> to generate permanent, unique react keys.