Why not to use index as key in React Lists (Practical Example)

We all have heard that using index as key in a react list is an anti-pattern and should be avoided.
The answer to this lies in the concepts of:

  • React Virtual DOM: It's a lightweight representation of actual DOM, stored in memory and is never rendered.
  • Reconciliation in React: The process of syncing Virtual DOM with the real DOM.
  • Diffing Algorithm: The algorithm to find the minimum number of steps needed to update the real DOM.
  • Assumptions for using the Diffing Algorithm:
    • Two elements of different types will produce different trees.
    • The developer can hint at which child elements may be stable across different renders with a key attribute.

This is just a very brief overview of these concepts. For more details definitely checkout React Documentation. For now let's just keep in mind the 2nd assumption used for React's diffing algorithm and proceed further.

Coming back to our topic of why a key attribute is necessary.
React uses key attribute to track the changes in the list.
We might face following issues when we use index value as key attribute when creating a list:

  1. Performance Issues due to unnecessary re-renders.
  2. Issues in data mapping in case list items are sorted, filtered, or deleted.

Let's understand the performance issue with the following example.

Suppose we've a list of elements, with key attribute as index.

<ul>
  <li key=1>Milk</li>
  <li key=2>Eggs</li>
  <li key=3>Bread</li>
</ul>

Now, in case of any state change in the list, React just iterates over each list item in both the lists (React compares the Virtual DOM snapshot before the update and after the update), looks for changes and finally updates the RealDOM with only those changes.

If we add an item to the end of the list, React no longer needs to re-render the first 3 list items which are same. It will just add a new list item at the end.

<ul>
  <li key=1>Milk</li>
  <li key=2>Eggs</li>
  <li key=3>Bread</li>
  <li key=4>Butter</li>
</ul>

But suppose we add the new item at the beginning of the list.

<ul>
  <li key="1">Butter</li>
  <li key="2">Milk</li>
  <li key="3">Eggs</li>
  <li key="4">Bread</li>
</ul>

Now, the key of remaining list items also changes, which makes React re-render all the elements again, instead of just adding a new item at the end.

This can be avoided if we use some unique id as a key rather than index. Let's again consider the same previous example but this time by using a unique id as key.

<ul>
  <li key="12abc">Milk</li>
  <li key="23bcd">Eggs</li>
  <li key="34cde">Bread</li>
</ul>

Now even if we add element to the beginning or the end, we won't face an issue since keys are different. Since React tracks all list items with their key attribute, after adding a new element it would not re-render the previous list items.

<ul>
  <li key="45htl">Milk</li>
  <li key="12abc">Milk</li>
  <li key="23bcd">Eggs</li>
  <li key="34bcd">Bread</li>
  <li key="85kgt">Milk</li>
</ul>

In the below example, the first list is created using index as key and in the second using id as key. On deleting the item from the first list, we can see the whole list is getting re-rendered, while in the second list the original list remains intact only the targeted element is removed. So, in case the list is large with complex components it might cause a huge performance issue. screen-capture-1

When is it safe to use index as key in a list?

  1. Data is static.
  2. When you know reordering of lists: Sorting, Filtering is not going to happen.
  3. In the absence of an id.

SUMMARY

  1. Always prefer using a unique id as value for the key attribute in a list and avoid using index.
  2. Using index might result in performance issues and data binding issues in case reordering in the form of sorting, filtering might happen.

References:

  1. Reconciliation - React
  2. Virtual DOM and Internals - React
  3. Understanding React's UI Rendering Process
  4. [Why do I need Keys in React Lists?](programmingwithmosh.com/react/why-d