Why using an index as Key in React is probably a bad idea?

Jan 24, 2018 · 2 min read

Let’s say you have a list of items and you want to show them as ul, li elements in your React app. When the user clicks on one of the list item, you want to remove that item and re-render the list.

In React, you would do something like this (for brevity, only the relevant code is shown. Full example is in here: https://codesandbox.io/s/pkqrj851nq)

Render a list of Items — Using the loop “index” as Key for the children

Of course, in React, you are required to pass in a unique key value for all elements of an array. Else, you will see this warning in console.

Warning: Each child in an array or iterator should have a unique “key” prop.

So, as a lazy developer, you would simply pass in the loop’s index value as the key value of the child element.

{this.state.fruits.map( (fruit, index) => <li key={index} ... /> )}

With the above code, you will see the list rendered as below.

With index as Key, removing any item will always apply the transition to the last item

Notice how the leave transition is always applied to the last item in the list, even though correct item was removed? This isn’t what we want, is it?

The reason is because you are not passing an unique key for each child element in the list. Without a unique key, React couldn’t differentiate if the element was removed or just the content is changed.

So, when you remove the first item in the list, React’s diff algorithm thinks only the content got changed, because the key is not changed. So, it just updates the content and not physically removing the first element from DOM, hence the leave animation is not getting applied. But when it comes to the last element, as one item was already removed from list, React thinks the last item was removed and it physically removes the last item from DOM, thus applying the leave animation.

To fix, we just need to make sure to pass in a unique key value for each child elements. For our case, we could just pass in the item name, instead of it’s index.

{this.state.fruits.map( (fruit, index) => <li key={fruit} ... /> )}

Notice the change in key value. With this fix, we will end up with this result.

With unique key, removing an item will correctly apply ‘leave’ transition to it.

You can find the source code for this example in here: https://codesandbox.io/s/pkqrj851nq

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade