Written by - Saksham Jain

Understanding unique keys for array children in Reactjs


Be careful when iterating over arrays!!

It is a common misconception that using the index of the element in the array is an acceptable way of suppressing the error you are probably familiar with:

Each child in an array should have a unique "key" prop.

However, in many cases it is not! This is anti-pattern that can in some situations lead to unwanted behavior.

Understanding the key prop

React uses the key prop to understand the component-to-DOM Element relation, which is then used for the reconciliation process.
It is therefore very important that the key always remains unique, otherwise there is a good chance React will mix up the elements and mutate the incorrect one.
It is also important that these keys remain static throughout all re-renders in order to maintain best performance.

That being said, one does not always need to apply the above, provided it is known that the array is completely static. However, applying best practices is encouraged whenever possible.

In short, a key should be:
  • Unique - A key cannot be identical to that of a sibling component.
  • Static - A key should not ever change between renders.

Using the key prop

As per the explanation above, carefully study the following samples and try to implement, when possible, the recommended approach.

Bad (Potentially)

<tbody>
    {rows.map((row, i) => {
        return <ObjectRow key={i} />;
    })}
</tbody>

This is arguably the most common mistake seen when iterating over an array in React. This approach isn't technically "wrong", it's just... "dangerous" if you don't know what you are doing. If you are iterating through a static array then this is a perfectly valid approach (e.g. an array of links in your navigation menu). However, if you are adding, removing, reordering or filtering items, then you need to be careful.

Good

componentWillMount() {
  let rows = this.props.rows.map(item => { 
    return {uid: SomeLibrary.generateUniqueID(), value: item};
  });
}

...

<tbody>
    {rows.map((row) => {
        return <ObjectRow key={row.uid} />;
    })}
</tbody>
This is also a good approach. If your dataset does not contain any data that guarantees uniqueness (e.g. an array of arbitrary numbers), there is a chance of a key collision. In such cases, it is best to manually generate a unique identifier for each item in the dataset before iterating over it.

Preferably when mounting the component or when the dataset is received (e.g. from props or from an async API call), in order to do this only once, and not each time the component re-renders.

There are already a handful of libraries out there that can provide you such keys.