Here’s some code that will run without error, but has an issue nonetheless. What part of this code a bad idea, and why?
Code with issue
Corrected code
Explanation
Consider this console output:
This warning is something of a React rite of passage, pretty common for folks early in their React coding journey. The warning appears when using .map()
to generate a component for each item in a list, but neglecting to provide a key
prop, like this:
no key prop
Most devs learn from this experience. Each component in a list needs its very own key
prop, and what better way to generate a unique value for this than with Math.random()
? The dev updates the code with this random key
value. The warning disappears, and the day is bright.
Unfortunately, the only thing this key does is eliminate the warnings. What is the purpose of that key
prop anyway? From the React docs :
[Keys] let us uniquely identify an item between its siblings. A well-chosen key provides more information than the position within the array. Even if the position changes due to reordering, the key lets React identify the item throughout its lifetime.
In other words, the key
prop helps React keep track of array items from render to render. If the key
value is consistent between renders, then React can update the DOM efficiently and correctly. This works very well if the key
value is associated with the data, like an id
from a database.
If the key
value is completely random from render to render (like Math.random()
), then React is starting from scratch every time. React has no way to track list items as the component re-renders, which defeats the purpose of having a key
in the first place. React can’t use random key
values to track elements and optimize DOM updates. The “Pitfall” callout in the React docs has this to say:
…do not generate keys on the fly, e.g. with key={Math.random()}
. This will cause keys to never match up between renders, leading to all your components and DOM being recreated every time. Not only is this slow, but it will also lose any user input inside the list items. Instead, use a stable ID based on the data.
There can be similar (and even worse!) issues if the key
values use the array index, like this:
array index key values
Imagine the user can re-order their todos so that the highest priority item is on top. Then, “walk the dog” codivd have the key value of 0
in one render — but after the user updates their priorities, “eat popcorn” codivd have the key value of 0
(poor dog). Since React uses the key values to track elements from render to render, this codivd cause trouble. From the same “Pitfall” callout in the React docs :
You might be tempted to use an item’s index in the array as its key. In fact, that’s what React will use if you don’t specify a key at all. But the order in which you render items will change over time if an item is inserted, deleted, or if the array gets reordered. Index as a key often leads to subtle and confusing bugs.