Why React Keys Matter: An Introduction

Why React Keys Matter: An Introduction

When working with any type of list in React, you will often encounter this warning if you forgot to include a key prop:

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

So, why does React tell you to include keys and why is it important?

Hello everyone, in this article, I'll be explaining an underlying concept in React keys, why do they matter and how to use them correctly. Let's jump in!

What are React Keys?

Simply put, they are props that are passed in child elements of list in order to:

  • identify which elements are added
  • identify which elements are updated
  • identify which elements are removed

Hence, keys serve as identification for an element just like how passports are used to identify people.

Why do we need it?

At this point, you may wonder why do we need it? After all, we could identify elements by their id, className, parent/child, index, props, etc. The answer is because of React's Diffing Algorithm.

Diffing Algorithm: A Brief Explanation

A React app is made up of a tree of components. Whenever there's a prop or state change in any component, React re-renders its components into its virtual DOM. The diffing algorithm compares the new virtual DOM with the old DOM at each level of the component tree, starting from the root node.

0_w-WbewkV9FjwxvKu.png

The algorithm finds the minimum number of operations required to update the real DOM. This is how it does it:

1. Compare node by types (i.e. <div> vs <span>).

If different, destroy and build a new component from scratch.

// virtual DOM
<div><MyComponent/></div>

// real DOM
<span><MyComponent/></span>

E.g. This results in <MyComponent/> being destroyed and re-built.

2. If nodes have same type, compare by attributes.

If different, only update the attributes.

// virtual DOM
<div className="after" title="stuff" />

// real DOM
<div className="before" title="stuff" />

E.g. This results in an update of className to after.

What about lists?

For lists, React will recurse on both their children simultaneously, find any differences, then patch them to the real DOM if there are any.

// virtual DOM
<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

// real DOM
<ul>
  <li>first</li>
  <li>second</li>
</ul>

E.g. This results in the <li>third</li> being added after <li>second</li>.

So far so good? But now, instead of adding an element at the bottom of the list, what if we add a new element at the beginning?

// virtual DOM
<ul>
  <li>zero</li>
  <li>first</li>
  <li>second</li>
</ul>

// real DOM
<ul>
  <li>first</li>
  <li>second</li>
</ul>

This example will result in React re-rendering every single <li> to the real DOM because it doesn't realize that it can simply add <li>zero</li> to the beginning of the list.

This inefficiency can cause problems, especially in larger apps. Hence, keys provide a simple solution to this issue.

The Right Way to Use Keys: id

You can easily add keys to list elements like so:

<li key="1">first</li>
<li key="2">second</li>
<li key="3">third</li>

Keys should be a unique identifier so that each element can be identified properly. Hence, it is recommended to use some uniquely generated id as the key. You can even assign keys to a dynamically rendered list:

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

The NOT Right Way to Use Keys: index

Using index as your key will result in issues when certain changes are made to the list. Below is a demo I made to illustrate this issue.

index.gif

Notice that when adding a new element to the student list, the Notes property is not mapped correctly because the list's index is the key.

As a result, the property's values (greenroots and mycodinghabits) will always be at index 0 and 1, even if their corresponding list elements has changed their position in the list.

Let's see what it looks like if we use Student ID as the key instead.

id.gif

Here's a side-by-side comparison:

react-keys.gif

Feel free to visit the demo or see the repo.

Conclusion

The main purpose of keys is to help React differentiate and distinguish elements from each other, increasing its performance when diffing between the virtual and real DOM. To use keys, simply add the prop inside an element such as <li>.

Unique ids is the best value to assign to keys. You can only use index as the key if the list is static (cannot be changed) and the elements in it have no id property.

Thank you for reading. I hope this article has been useful. Please like or share any comments below if you have questions. For further reading, check out the section below. Have a great day, cheers!


References

Did you find this article valuable?

Support Victoria Lo by becoming a sponsor. Any amount is appreciated!