Introduction
React.js uses a number of unique concepts that can initially seem a bit confusing. One such concept is the use of keys, particularly when working with component arrays. Why and how do we use these keys? This article aims to explain the use of unique keys for array children in React.
Keys in React
In React, a key is a string attribute you need to include when creating lists of elements. Let's take a look at a simple example:
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
In this example, we're creating a list of numbers. Each <li>
element needs a unique key attribute. Here, we're using the string value of the number as the key.
These keys serve as a hint to React's reconciliation algorithm by giving elements a stable identity. They're not intended to be globally unique; they only need to be unique between components and their siblings.
But why do we need keys in the first place? Well, keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside an array to give the elements a stable identity, and therefore easier access.
It's worth noting that the best way to pick a key is to use a string that uniquely identifies a list item among its siblings. A common way to do that is to use IDs from your data as keys:
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);
Here, we assume that todos
is an array of objects with an id
and a text
attribute. The id
of each todo
object is unique, so it makes a good candidate for a key.
But what happens if you don't have a unique ID or string to use as a key? In that case, you might be tempted to use the item index as a key:
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);
However, this is generally not recommended. Index as a key is an anti-pattern in React because it can negatively impact performance and may cause issues with component state. It's better to use unique string identifiers if possible.
But why do we need these keys?
In React.js, whenever we create a list or array of elements, each element needs a unique key
attribute. This might seem like an unnecessary step at first, but it's actually crucial for React's diffing algorithm, which helps optimize the rendering process.
When a component's state changes, React needs to determine whether to update the existing DOM or create a new one. This is where the diffing algorithm comes into play. It compares the new virtual DOM with the old one and updates only the parts that have changed.
he diffing algorithm increases performance by minimizing the amount of DOM manipulation.
By assigning a unique key to each element in a list, you're giving React a way to identify each element in the array. This allows React to efficiently re-render components or update the DOM. Without unique keys, React has to re-render all elements in the list, which can reduce performance, especially when dealing with large lists.
How to Use Unique Keys with Array Children
Now that we understand why unique keys are important, let's see how we can use them with array children. The most common scenario where you'll need to use unique keys is when rendering a list of elements based on an array of data.
Let's take a look at our previous example, but more in-depth. Here we have an array of to-do items and we want to render them into a list:
const todos = ['Buy groceries', 'Walk the dog', 'Write article'];
return (
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
);
In this example, we're using the array index as a key. This is a common practice, but it's not recommended if the order of items in your list can change. This is because the key should be stable between re-renders, and using the index as a key can cause issues if the order of items changes.
Here's how you could do that:
const todos = [
{ id: '1', text: 'Buy groceries' },
{ id: '2', text: 'Walk the dog' },
{ id: '3', text: 'Write article' },
];
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
In this example, each todo
item is an object with a unique id
and text
. We're using the id
as a key, which ensures that each element in the list has a unique key that remains stable between re-renders.
How to Fix and Avoid Key Related Errors
One of the most common errors that developers encounter when working with keys in React is the "Warning: Each child in a list should have a unique 'key' prop" warning. This warning appears when you forget to assign unique keys to your list items.
The simplest example we can show is where we're mapping over an array of numbers and returning a list of elements:
const numbers = [1, 2, 3, 4, 5];
return (
<ul>
{numbers.map((number) =>
<li>{number}</li>
)}
</ul>
);
You'll notice that we didn't provide a key
prop to our list items. Running this code will result in the previous warning.
To fix this, we simply need to assign a unique key to each list item. In this case, we can use the array index as the key:
const numbers = [1, 2, 3, 4, 5];
return (
<ul>
{numbers.map((number, index) =>
<li key={index}>{number}</li>
)}
</ul>
);
Other Key Related Errors
Another common key-related issue in React is using keys that are not unique. This can lead to unexpected behavior, as React relies on keys to correctly identify elements.
For instance, consider the following example:
const numbers = [1, 2, 3, 4, 5, 5];
return (
<ul>
{numbers.map((number) =>
<li key={number}>{number}</li>
)}
</ul>
);
In this case, we have two 5
s in our array, which means two list items will have the same key. This will result in a new warning: "Encountered two children with the same key".
To fix this error, you need to ensure that your keys are unique. You could do this by appending the index to the number:
const numbers = [1, 2, 3, 4, 5, 5];
return (
<ul>
{numbers.map((number, index) =>
<li key={number + '-' + index}>{number}</li>
)}
</ul>
);
In this code, even if the numbers are the same, the keys will be unique because the index is part of the key.
Although, as mentioned a few times before, using the array index as a key is not recommended.
Conclusion
In this article, we've taken a look at the concept of unique keys for array children in React.js. Like what keys in React are, why we need unique keys, how to use them with array children, and how to fix and avoid key related errors.
So, the next time you're mapping over an array in React, remember to give each child a unique key. It's a small step that can save you from a lot of potential headaches down the line.