Why do you need the key prop when rendering lists?

Understand what really happens when you don't pass the key prop when rendering a list in React

Have you ever wondered why the key prop is so required when rendering lists in React? In this article, I will break down why you need to pass the prop, and what might happen when you don't.

Rendering data from arrays

Here is an example that I have plagiarised from the React docs. The following code will iterate through each person, and display it inside a <li> tag.

function People() {
    const people = [
      'Creola Katherine Johnson: mathematician',
      'Mario José Molina-Pasquel Henríquez: chemist',
      'Mohammad Abdus Salam: physicist',
      'Percy Lavon Julian: chemist',
      'Subrahmanyan Chandrasekhar: astrophysicist'
    ];

    return (
        <ul>
            {people.map(person => <li>{person}</li>)}
        </ul>
    )
}

What is the key prop?

If you've been using React for a while, you likely will have seen the following error:

Warning: Each child in a list should have a unique "key" prop.

But what is the key prop actually for? I've never encountered any issues not passing a key prop. According to the React Docs:

Keys tell React which array item each component corresponds to, so that it can match them up later. This becomes important if your array items can move (e.g. due to sorting), get inserted, or get deleted. A well-chosen key helps React infer what exactly has happened, and make the correct updates to the DOM tree.

None of the above explains what happens if I don't pass a key prop. But after a lot of research, I have been able to demonstrate a concrete example.

DOM state outside of React

The first example of when the key prop is needed is when there is state managed in the DOM, not React. For example, state managed by the DOM can include form inputs, scroll position, CSS transitions etc.

In the example below, I have an array of numbers: [1, 2, 3, 4, 5] . These numbers are rendered as a list alongside an uncontrolled text input. I have populated the defaultValue attribute with the number.

When you shuffle the list, the order of the numbers changes, but the values in the input fields do not. This is because React cannot track the values accurately when committing the changes to the DOM.

The below example is exactly the same, except the key prop is passed into each list item. As you can see, the input values are correctly updated.

What if I pass the array index as the key?

If you don't pass anything to the key prop, React uses the index as the key by default. So you will have the same issue as the above example.