The significance of React keys - a visual explanation
Tags: react, javascript, beginners, explainlikeimfive
Published: 2018-02-15 17:54:20

---
title: The significance of React keys - a visual explanation
published: true
description: Why correctly setting keys on mapped elements can give you a significant performance boost
tags: React, Javascript, Beginners, explainlikeimfive
cover_image: https://thepracticaldev.s3.amazonaws.com/i/0j7d9m2xku9l73fjz7jk.jpg
---

_Disclaimer: This is a gross oversimplification and should be used as a basic guide on how reconciliation works, not a perfect example!_

When handling arrays in React, utilisation of the 'key' attribute on each element can be crucial for avoiding needless rerender performance hits. This article will hopefully explain why you should always clearly define your keys, and what you are missing out on if you are not doing so.

Let us start with an array

```javascript
const joshs = [{  Name: "Josh", }, { Name: "Joshina", }, {  Name: "Notjosh", }]
```

the business end of our React component which renders said array

```jsx
<div>
    { joshs.map((person, index) => ( <span key={index}>{person.name}</span>)) }
</div>
```

and the HTML it outputs

```html
<div>
    <span key=’0’>Josh</span>
    <span key=’1’>Joshina</span>
    <span key=’3’>Notjosh</span>
</div>
```

Works great!


...but!

A new Josh has arrived, and he's told the others to move out of the way.


```javascript
 [{ Name: "Mega Josh"}, {  Name: "Josh", }, { Name: "Joshina", }, {  Name: "Notjosh", }]
```

Our component receives the new list, does its thing...

```jsx
<div>
    { joshs.map((person, index) => ( <span key={index}>{person.name}</span>)) }
</div>
```

and prints it out like it did before.

```html
<div>
    <span key=’0’>Mega Josh</span>
    <span key=’1’>Josh</span>
    <span key=’2’>Joshina</span>
    <span key=’3’>Notjosh</span>
</div>
```

Works great!

...but!

Let us look under the hood on what's actually happening (in a very simplified fashion) with the process that React is going through when it renders its new list.

A React component, when you boil it down to its rawest form (i.e. convert it from JSX), is just an object with a set of properties. These properties define its type, name, state, what props it has received, whether it has children, etc. 

Each time a change occurs in our array, a new list of Josh `<span>` component objects are created. The React [reconciler](https://reactjs.org/docs/reconciliation.html) will compare the newly created objects with the current versions it has in the DOM. If any differences are detected between certain properties, it will redraw the components believing that it's the same object, but properties have changed.

So with our example, we have our original array (of components), which can loosely be translated to something like this...

```javascript
[{
  Type: "span",
  Key: "0",
  Children: "Josh"
}, {
  Type: "span",
  Key: "1",
  Children: "Joshina"
}, {
  Type: "span",
  Key: "2",
  Children: "Notjosh"
}]
```

The reconciler will look at the key, and the component properties (in our simplified case, the content or children), and then look through its previous list of components to see if it matches any previous combinations.

As our list uses the array index position as its key, when 'Mega Josh' arrives and shifts all the components down one position, every comparison now fails due to React noticing that the keys do not match their previous properties!


```javascript
[{
  Type: "span",
  Key: "0",                // Expected 0 to match 'Josh'
  Children: "Mega Josh"     // IM DIFFERENT, REDRAW ME
}, {
  Type: "span",
  Key: "1",                // Expected 1 to match 'Joshina'
  Children: "Josh"          // IM DIFFERENT, REDRAW ME
}, {
  Type: "span",
  Key: "2",                // Expected 2 to match 'Notjosh'
  Children: "Joshina"       // IM DIFFERENT, REDRAW ME
}, {
  Type: "span",   
  Key: "3",                // IM NEW
  Children: "Notjosh"       // DRAW ME
}]
```

But! We can prevent this. If we clearly define a key which is static, unique, _and_ uniquely associated with the properties it is related to, React can acknowledge that it's the same component, even when it has changed its position.

Let us rebuild our components with unique keys 

_n.b. In this example I use the `name` attribute to keep our josh objects simple, but this is not best practice as the likelihood of two components having the same key is quite high. Where possible you should always use some sort of primary key from the data object._

```jsx
<div>
    { people.map((person, index) => ( <span key={`key-${person.name}`}>{person.name}</span>)) }
</div>
```

the exported HTML will now look like

```html
<div>
    <span key=’key-Josh’>Josh</span>
    <span key=’key-Joshina’>Joshina</span>
    <span key=’key-Notjosh’>Notjosh</span>
</div>
```

and the updated array HTML

```html
<div>
    <span key='key-Mega Josh'>Josh</span>
    <span key=’key-Josh’>Josh</span>
    <span key=’key-Joshina’>Joshina</span>
    <span key=’key-Notjosh’>Notjosh</span>
</div>
```

The keys are now unique to their data object (rather than their array position), so when we do our object comparison

```javascript
[{
  Type: "span",
  Key: "key-Josh",
  Children: "Josh"
}, {
  Type: "span",
  Key: "key-Joshina",
  Children: "Joshina"
}, {
  Type: "span",
  Key: "key-Notjosh",
  Children: "Notjosh"
}]
```

the reconciler will see that some components haven't changed, they have simply moved, only the new component will be created and inserted at the front of the list, not affecting the components after it. Brilliant!

```javascript
[{
  Type: "span",
  Key: "key-Mega Josh",    // IM NEW
  Children: "Mega Josh"     // DRAW ME
}, {
  Type: "span",
  Key: "key-Josh",         // Expected 'key-Josh' to match 'Josh'
  Children: "Josh"          // IM THE SAME, DONT REDRAW ME
}, {
  Type: "span",
  Key: "key-Joshina",      // Expected 'key-Joshina' to match 'Joshina'
  Children: "Joshina"       // IM THE SAME, DONT REDRAW ME
}, {
  Type: "span",
  Key: "key-Notjosh",      // Expected 'key-Notjosh' to match 'Notjosh'
  Children: "Notjosh"       // IM THE SAME, DONT REDRAW ME
}]
```

For some uses, the performance impact may be minimal (or even non-existant if the array never changes order). The benefits with adding keys will be noticeable with very large arrays that get sorted/re-ordered as it will eliminate the need for a majority of your list to be rendered. Magic!