React List and Keys
Lists are an important aspect within your app. Every application is bound to make use of lists in some form or the other. You could have a list of tasks like a calendar app, list of pictures like Instagram, list of items to shop in a shopping cart and so on. The use-cases are numerous. Lists within an application can be performance heavy. Imagine an app with a huge list of videos or pictures and you keep getting thousands more, as you scroll. That could take a toll on the app?s performance.
Because performance is an important aspect, when you are using lists you need to make sure they are designed for optimal performance.
Did you know that in React, when you use lists, each list item needs a unique key? Let?s learn more about lists and keys in React, and how to implement it the right way.
Rendering a simple List component
function ListComponent(props) { const listItems = myList.map((item) => <li>{item}</li> ); return ( <ul>{listItems}</ul> );}const myList = [“apple”, “orange”, “strawberry”, “blueberry”, “avocado”];ReactDOM.render( <ListComponent myList={myList} />, document.getElementById(‘root’));
The code above shows a ListComponent that renders a list of items that are passed to it as props. In the render() method we have invoked the ListComponent and passed to it a list myList as the props. This code will generate the following output:
- apple
- orange
- strawberry
- avocado
But when you run this code, you will notice that React also throws a warning.
?Warning: Each child in an array or iterator should have a unique ?key? prop.%s%s See https://fb.me/react-warning-keys for more information.%s?
Notice here that the warning is about using a unique key. Keys are necessary to improve performance of your React app, and we will see how.
How do you use Keys in Lists?
Keys help React identify which items have changed (added/removed/re-ordered). To give a unique identity to every element inside the array, a key is required.
To better understand this, let?s refactor the code snippet we saw earlier, to now include keys.
function ListComponent(props) { const listItems = myList.map((item) => <li key={item.id}> {item.value} </li> ); return ( <ul>{listItems}</ul> );}const myList = [{id: ‘a’, value: ‘apple’}, {id: ‘b’, value: ‘orange’}, {id: ‘c’, value: ‘strawberry’}, {id: ‘d’, value: ‘blueberry’}, {id: ‘e’, value: ‘avocado’}];ReactDOM.render( <ListComponent myList={myList} />, document.getElementById(‘root’));
In the code snippet above you can notice that I have included a key to each list item. Observe, that I have updated my original list to be a value-id pair. Each item in the array has an id associated with it. Hence, this is the id that is assigned as a key for each item. This is the best approach to assign unique keys for items on a list.
In this method, the key is a unique string that identifies each item.
Can I just use indexes as keys? ? Only under some exceptions
Checkout this article by Robin Pokorny about Index as a key is an anti pattern. You may wonder, why don?t we just use indexes as keys when looping through an array. Although, many developers have done that in their code it is not necessarily ideal. React recommends that you do not use indexes as keys, since it could impact performance negatively and could lead to some unstable component behaviour.
const todoItems = todos.map((todo, index) => // Only do this if items have no stable IDs <li key={index}> {todo.text} </li>);
In the example above you can see we are looping through the todos and assigning the index of each item as the the key. This is acceptable for some use cases that we will see below.
Reordering a list, or adding and removing items from a list can cause issues with the component state, when indexes are used as keys. If the key is an index, reordering an item changes it. Hence, the component state can get mixed up and may use the old key for a different component instance.
Therefore, avoid this practice, and make sure unique ids are generated to be assigned as key.
There are some situations when assigning the index as a key maybe acceptable.
What are some exceptions where it is safe to use index as key?
- If your list is static and will not change.
- The list will never be re-ordered.
- The list will not be filtered (adding/removing items from the list).
- There are no ids for the items in the list.
If all these exceptions qualify, then you can use an index as a key.
Note: Using index as a key can lead to potential unexpected behaviour within the component.
Keys need to be Unique, but only among its siblings
It is useful to keep in mind that although a key for each item needs to be unique, this rule applies only within an array. In other words, each item within an array needs to have a unique key, but it does not have to be globally unique. The same key can be used across several other components and lists that are unrelated.
Keys don?t automatically get passed as a prop to the component
In the example below, you can see that I am explicitly passing the item.id which is the key as another prop (id) to the component. This is because React does not automatically pass they key like a prop. If you wanted to use the key for some computation, you would need to pass it as another prop like we did in this example.
const content = items.map((item) => <MyComponent key={item.id} id={item.id} title={item.title} />);
In this example the MyComponent can read props.id and prop.title but not props.key.
Conclusion
Let?s recap the highlights from this post.
- Lists are performant heavy and need to be used carefully.
- Make sure every item in the list has a unique key.
- It is prefered to not use indexes as a key unless you know for sure that the list is a static list (no additions/re-ordering/removal to the list).
- Never use unstable keys like Math.random() to generate a key.
- React will run into performance degradation and unexpected behaviour if unstable keys are used.
If you enjoyed this post, please share it and you can follow me on Twitter @AdhithiRavi
This article was originally published on https://programmingwithmosh.com/react/why-do-i-need-keys-in-react-lists/