Warning: Each child in a list should have a unique "key" prop.
This tutorial talks about what that error means, and how (and why) to fix it.
As the state changes, React’s
render() function returns a new tree of React elements, and then here’s the important part: React only updates parts of the DOM that have changed.
Here’s an example:
Use your browser’s developer tools to inspect the elements in this example, and then try clicking the button. (Click here to open the example in a new tab.)
render() function of the
App component returns a few React elements, which are then converted to HTML elements and added to the DOM. But notice that only the
<p> element in the middle changes, and the rest of the DOM stays the same.
This is part of the magic of React: as a component’s state changes, React only modifies parts of the DOM that have changed, and leaves the rest of the DOM alone.
Now you’ve seen that React only updates parts of the DOM that have changed.
Here’s another example:
Use your browser’s developer tools to inspect the elements in the list, and then try adding and removing items. (Click here to open the example in a new tab.)
Notice where the DOM changes as the state changes. Specifically, notice that when you add or remove an item from the beginning of the list, every subsequent list element also changes, even though their content isn’t actually changing.
That’s because React isn’t smart enough to understand when content moves but doesn’t change. If you have a list like this:
And then you add an item to the beginning of the list:
…React will see that
Apples changed to
Bananas changed to
Strawberries changed to
Bananas, and that a new
Strawberries item was added to the end. And since React thinks that the content of ever list item has changed, it updates every
<li> element in the DOM.
That might be okay for a small page like this. But as your page becomes more complicated, updating the DOM becomes more expensive. To help avoid unnecessary updates, React uses keys to track elements that might move and change.
To use keys, add a
key attribute to elements that are generated from a loop or list. The value can be anything you want, but each sibling element should have a unique key value. Key values can be the underlying ID in the data, an ID that you increment over time, or a UUID.
If the state contains an array of items, and each item already has an ID, here’s how you might use those IDs as keys:
Here’s the same example from before, this time with keys added:
Use your browser’s developer tools to inspect the elements in the list, and then try adding and removing items.(Click here to open the example in a new tab.)
Notice that only the added or removed element changes, and the rest of the DOM stays the same. That’s because React is now using the keys to determine which parts of the DOM have actually changed.
When choosing a value for your keys, you might be tempted to use a loop index as the key value. After all, you’re already looping over an array, so you might as well use the index, right?
And yes, you could do something like this:
this.state.items.map((item, index) =>
However, this approach won’t actually prevent React from re-rendering every item! Here’s why: Let’s say you started with these items and keys:
And then your data changed to include a new item:
If you’re using the indexes as keys, React’s rendering logic will go something like this:
0 had a content of
Apples, but now it has a content of
Oranges. That means I need to re-render it!
1 had a content of
Bananas, but now it has a content of
Apples. That means I need to re-render it!
In other words, you’re back to the original problem of React not being smart enough to tell the difference between an element that has moved and an element that has changed.
So when in doubt, don’t use indexes as keys!
Use your browser’s developer tools to inspect the elements in the list, and then try marking a task as completed.(Click here to open the example in a new tab.) Notice how the DOM only updates the elements that have changed!