A puppy dies every time you set key={index}
Every React element has a special key
prop. It has a single purpose: ** to uniquely identify a React element**.
There are two circumstances in which you as a React developer can use the key
prop to your advantage:
- to prevent an element from being unnecessarily re-rendered (the most common)
- to force an element to be re-rendered (advanced, used only in rare circumstances)
Preventing unnecessary re-rendersSection titled: Preventing unnecessary re-renders
Far and away the most common and useful purpose of the key
prop is to prevent unnecessary re-renders of a component that is created by mapping over an array.
Using it usually looks something like this:
đ But how does using key
prevent unnecessary re-renders?
key
prevents unnecessary re-renders by allowing React to determine that an element still exists, unchanged from the last render, it just may have moved.
đ How does that work?
Remember that keyâs only purpose is to uniquely identify a React element. Every time each one of those <li>
elements is rendered, React will do a âdiffâ (calculate the âdifferenceâ) between the previous element that was rendered with a particular key
and and current element that is being rendered with that key. If there is no difference between the two, React will not modify that element in the DOM. If it does find a difference, React will unmount the previous component instance, create a new component instance, and mount that one instead.
The key
prop wonât/canât/shouldnât do anything to prevent a component from re-rendering if it has changed. But it can & should prevent a component from re-rendering if it has only moved!
đ Can you give a more concrete example?
What happens if you reverse the items
array from the above snippet? Well, with our current code, React wouldnât create or destroy a single <li>
element! It would simply re-arrange the existing <li>
s to match the new order of the array. And how does React know where to place each element? Because of itâs unique key
of course!
Moving existing DOM nodes is much more performant than destroying and re-creating nodes.
The wrong way â using index as the keySection titled: The wrong way â using index as the key
Letâs contrast our previous implementation to a very common, yet incorrect one:
Youâll see this key={index}
in tutorials and production code alike, but its usage is lazy and has negative performance implications.
The catch is though, that oftentimes those performance implications crop up later, well after the key={index}
code was initially written.
đ But why is key={index}
bad?
If the contents of the array that youâre mapping over is guaranteed never to change in any way, then there wouldnât be a performance hit caused by setting key to index.
But in my experience, there is almost no array (or code in general) that is guaranteed never to change in any way.
Sure, the code youâre writing today has no way for the array to change. But what happens next month when product wants toâŚ
- add sort functionality to the UI?
- allow the user to add items to the list?
- delete items?
- drag and drop to re-order items?
- filter the list?
- search for items in the list?
Every one of those features will be negatively impacted by key={index}
.
The developer adding that new feature might be a different member of your team, and they might never have to touch the file that you wrote key={index}
in, so they donât know about it. They just trusted you to do the right thing and you let them down đ.
đ Why is there a negative performance impact to key={index}
?
Consider the scenario where one single item is inserted to the middle of the array.
With key
being set to index, the key of every element after the added element will change. So even though none of those elements have actually changed, they will all be unmounted and have duplicate elements re-created and re-mounted in their place, a process that takes infinitely longer than just leaving the DOM nodes alone and adding the new element ot the middle.
This is equally true for sorting, filtering, searching, and every other type of operation listed in the bullets above.
Force an element to re-renderSection titled: Force an element to re-render
Weâve gathered by now that when an React elementâs key
changes, it is unmounted and a brand new component instance is created in its place.
Weâve also seen that far and away the most common place to use key
is inside of a .map()
function. But it doesnât have to be inside of a map. key
can exist on any React element.
So if you need to force a component to âre-renderâ in a situation that it otherwise wouldnât one way to approach that problem is to force a change to its key
.
What makes key so special?Section titled: What makes key so special?
The key
prop is special because it is one of only two props that are not accessible from within the component instance (the other being ref
).
In fact, if you attempt to access key
from within a component instance, youâll get a warning in your console:
But I donât have an id for this object đSection titled: But I donât have an id for this object đ
Inevitably, youâll run into a situation where you need to render a list of objects, but those objects donât come with prepackaged a unique identifier. Maybe theyâre coming from a third-party API, or maybe theyâre just a list of strings.
In cases like that, there are still a few options:
Option 1: Generate a random id for each objectSection titled: Option 1: Generate a random id for each object
If youâre fetching a list of objects from an API and they donât have a unique identifier, you can just add one yourself.
And just like that, you have a unique identifier for each item!
Option 2: Combine multiple properties into a keySection titled: Option 2: Combine multiple properties into a key
If none of your objectâs properties are guaranteed to be unique, but combined they are almost certain to be unique, that is usually good enough.