We have seen in a previous post why using indexes as keys when rendering lists in React is not a good idea, and how it can lead to bugs.
Therefore the question: so then what should I put in the key
prop if not the index
?
As I could not find a simple answer for this one, I went and did some research and this is what I found.
What to use as keys in React instead of index?
Below are some options for setting the key
value in React, while looping through a map(data, index)
function:
-
use the
id
field of the data. In most cases, we get data from an API request and we want to show that data in a list. Most likely the data that comes from the API is from a database, so it has anid
field or something similar. We can use this field as the value for thekey
property:// fetch the items from an API {items.map(item => ( <li key={item.id}> {item.description} </li> ))}
This is maybe the most straightforward option.
-
use the
randomUUID()
method from the Web Crypto API. Thewindow.crypto
interface is now available in all major browsers, so we can use it as a built way to generate React keys:{items.map(item => ( <li key={window.crypto.randomUUID()}> {item.description} </li> ))}
Special kudos to Paul for telling me about this option.
-
generate the key with an external library. One other way is to use a 3rd party library such as uuid or something similar:
npm install uuid --save
And, now we can do:
import { v4 as uuidv4 } from 'uuid' {items.map(item => ( <li key={uuidv4()}> {item.description} </li> ))}
A potential downside of this approach is that we may need to install extra libraries to our project.
-
a mix of
index
and one unique property. If the data doesn't have a unique identifier, and can't generate one, we can combine theindex
from themap()
with some unique property of the data:{items.map((item, index) => ( <li key={`${index}-${item.someUniqueProperty}`}> {item.description} </li> ))}
The overall idea here is to decouple the index
value from the key
.
Do not use the useId() hook to generate keys
React 18 introduced the useId() hook. It can seem like a perfect candidate for the key property:
// āļø don't use the useId hook for keys
import { useId } from 'react'
{items.map((item, index) => (
<li key={useId()}>
{item.description}
</li>
))}
But, please note that useId()
hook was introduced for accessibility attributes and was not intended for keys. This is from the official documentation:
Is it ever safe to use the indexes as keys in React?
Yes, there are some cases when we can use the index
as key
. For example when we won't do any manipulation of items. When we will not add, remove, or do something like letting users rearrange the order of the items.
However, using the index as part of the key should be the last resort, as it may lead to issues when the order of items changes or items are added or removed.
In conclusion, when setting keys in React, choose a unique identifier that remains consistent across renders. Prioritize unique identifiers such as an id from the data or you can use libraries such as uuid
for a more robust solution. Also, remember it's important to note that hooks like useId()
are not intended to not be used as keys.
š 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
š 50 Javascript, React and NextJs Projects
Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.
There’s a native way to generate a UUID, via crypto.randomUUID(), just in case you were unaware. This can be added to each object in an array with the map method before returning the JSX.
Thanks a lot, Paul! Good point. Did not realize that crypto is now available in all browsers. Updated the article š