A common anti-pattern in React components is the unnecessary use of array indices as key
values:
<ProductDashboard>
{products.map(({cost, description, name, sku}, i) => (
<Product
cost={cost}
description={description}
key={i}
name={name}
sku={sku}
/>
))}
</>
It's best to avoid index-based key
values — which are merely positional — whenever you have an alternative that is more closely related to the identity of an element. In example above, the SKU ("Stock Keeping Unit") is a unique identifier and would be a great choice for the key
attribute.
The reason is that React uses the key
as a hint to figure out how to best reconcile the DOM in a minimal way when changes are made. Imagine that your have a list of fruits which you render in two different states:
First render | Second render |
---|---|
1. Apple | 1. Apple |
2. Banana | 2. Banana |
3. Pear | 3. Pear |
4. Orange | 4. Apricot |
5. Apricot | 5. Peach |
6. Peach |
Consider what happens during the second render, having filtered the list so that "Orange" won't get rendered any more:
- If you use the names as keys, React can figure out that item "4. Orange" should be removed from the DOM, which is a single operation.
- If you use the indices as keys, React thinks you're telling it that item 4's name changed from "Orange" to "Apricot", item 5's name changed from "Apricot" to "Peach", and item 6 was removed, which is three operations.
For much more detail, see the React docs on reconciliation:
As a last resort, you can pass an item's index in the array as a key. This can work well if the items are never reordered, but reorders will be slow.