· Kalpa Madhushan · documentation · 3 min read
Understanding React Keys: The Right Way to Render Lists
Learn why you should provide a key prop when rendering lists in React and the pitfalls of using indices as keys.
Today, I’m going to talk about a very interesting and useful React hack. I know when we try to render an array of elements in React, we usually get this error. But we can remove that by simply using this code:
{items.map((item, index) => (
<div key={index}>{item}</div>
))}
But do you think the above code solves the issue? Actually, no. It makes the situation worse. You can’t understand what is happening here just by looking. We need to use a little trick to see the rendering part.
I assume you know how React DOM updates elements based on changed elements.
Here, I have used this code sample to render a list with inputs:
const items = [
{ name: 'Item 1' },
{ name: 'Item 2' },
{ name: 'Item 3' },
];
return (
<ul>
{items.map((item, index) => (
<li key={index}>
<input defaultValue={item.name} />
</li>
))}
</ul>
);
Now, I’m putting values into these inputs and clicking a button to add a new value to the beginning of the array. See what happens. If you compare the input fields, you can identify that the newly rendered element is the last list item, but actually, we added it as the first one. This is where we can identify the issue of adding the index as the key.
What’s happening here is that React DOM sees the key, and since the old and new elements both have the zero index, it doesn’t re-render the elements. It goes on and on until the last element. As you can see in the below chart, React DOM thinks this is the newly added item as it has a new index, so it adds a new component.
Another problem is adding random values for keys. This is even worse because this forces the DOM to re-render all list items. If I use the Math.random
function, as shown here, you can see that it renders all elements before and after because each element has different IDs each time.
The most efficient way we can solve this is by using object arrays with IDs like this:
const items = [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' },
];
return (
<ul>
{items.map(item => (
<li key={item.id}>
<input defaultValue={item.name} />
</li>
))}
</ul>
);
So every element has a unique ID. It doesn’t matter where we add that element; the DOM can easily identify which element changed and render the relevant component.
Use this method next time you render a list of items. Don’t use shortcuts; it will improve your code’s performance as the application and the amount of data become larger.