Rendering Lists in React: How to Map Arrays to JSX Elements
Suppose you want to create a list of React elements from an array of data. You can use the JavaScript map()
method.
Here’s an example:
import ReactDOM from "react-dom/client";
// Define the bestColors array:const bestColors = ["Blue", "White", "Pink"];
// Use the bestColors array to create a list of React elements:const bestColorsLiElements = bestColors.map((color) => <li>{color}</li>);
// Render the array of <li> elements to the root DOM:const root = ReactDOM.createRoot(document.getElementById("root"));root.render(<ul>{bestColorsLiElements}</ul>);
The snippet above used map()
to create a new list of React elements by converting each of bestColors
items to <li>
elements.
Notice that we rendered the list of elements directly in the root.render()
method. Typically, you would use a component to do such rendering. So, let’s do some refactoring by moving the bestColorsLiElements
variable and the <ul>
element into a component:
import ReactDOM from "react-dom/client";
function BestColor() { // Define the bestColors array: const bestColors = ["Blue", "White", "Pink"]; // Use the bestColors array to create a list of React elements: const bestColorsLiElements = bestColors.map((color) => <li>{color}</li>); return <ul>{bestColorsLiElements}</ul>;}
// Render the array of <li> elements to the root DOM:const root = ReactDOM.createRoot(document.getElementById("root"));root.render(<BestColor />);
Although, the snippet above displays the right content on the screen. However, React throws a console error. Let’s discuss the issue.
Each React Element in an Array Needs a Unique Key
Section titled “Each React Element in an Array Needs a Unique Key”If you check your console, you will see a warning message that says: Each child in a list should have a unique "key" prop.
The message means that whenever you create an array of elements, React needs you to specify a unique identity for each item in the list.
The unique identity keys help React identify changes to the array.
Let’s refactor the previous snippet so that each element in the bestColorsLiElements
has a unique key
prop.
How to Add Unique Keys to Each React Element in an Array
Section titled “How to Add Unique Keys to Each React Element in an Array”There are two common ways to assign unique keys to each element of an array. The first is the unrecommended way. While the second is the best technique.
Unrecommended way to assign keys to an array of React elements
Section titled “Unrecommended way to assign keys to an array of React elements”One way to add unique keys is to use each item’s index as its key
prop.
Here’s an example:
import ReactDOM from "react-dom/client";
function BestColor() { const bestColors = ["Blue", "White", "Pink"]; // Use each item's index as its key prop: const bestColorsLiElements = bestColors.map((color, index) => ( <li key={index}>{color}</li> )); return <ul>{bestColorsLiElements}</ul>;}
const root = ReactDOM.createRoot(document.getElementById("root"));root.render(<BestColor />);
The snippet above specified a key
prop on each <li>
element. It then used each item’s index
as the prop’s value.
Best way to assign keys to an array of React elements
Section titled “Best way to assign keys to an array of React elements”The best way to add unique keys to each React element in an array is to use stable IDs from either of the following sources:
- Database: Use the database-generated IDs as the
key
props if your data comes from a database, as they are unique by default. crypto.randomUUID()
incrementing counter: Use therandomUUID()
method to generate Universally Unique Identifiers if you are creating and storing your data locally. (Note: This method is a web API. So, it’s available only in supporting browsers’ HTTPS contexts.)uuid
: An NPM package for generating Universally Unique Identifiers if you are creating and persisting your data locally. This is a good alternative to therandomUUID()
method for cross-platform compatibility.
Here’s an example:
import { createRoot } from "react-dom/client";import { bestColors } from "./bestColors.js";
function BestColor() { // Use each item's id as its key prop: const bestColorsLiElements = bestColors.map((color) => ( <li key={color.id}>{color.name}</li> )); return <ul>{bestColorsLiElements}</ul>;}
const root = createRoot(document.getElementById("root"));root.render(<BestColor />);
export const bestColors = [ { id: crypto.randomUUID(), name: "Blue" }, { id: crypto.randomUUID(), name: "White" }, { id: crypto.randomUUID(), name: "Pink" },];
The snippet above specified a key
prop on each <li>
element. It then used each item’s id
as the prop’s value.
Important Things to Know About Assigning Keys
Section titled “Important Things to Know About Assigning Keys”Here are essential facts to remember whenever you assign keys to an array of React elements.
Set each array element’s key while creating the array
Section titled “Set each array element’s key while creating the array”The right place to specify each array element’s unique key is directly inside the map()
method while creating the list of elements.
In other words, say you extract your template element into a separate component. Set the key
prop on the component’s invocation tag—not on the extracted template element.
Example 1: Incorrect placement of the key prop
Section titled “Example 1: Incorrect placement of the key prop”import { createRoot } from "react-dom/client";import { bestColors } from "./bestColors.js";
function ColorListElement({ color }) { // WRONG: Don't place the key outside the map() method. return <li key={color.id}>{color.name}</li>;}
function BestColor() { const bestColorsLiElements = bestColors.map((color) => ( // The key attribute above should have been set here. <ColorListElement color={color} /> )); return <ul>{bestColorsLiElements}</ul>;}
const root = createRoot(document.getElementById("root"));root.render(<BestColor />);
export const bestColors = [ { id: crypto.randomUUID(), name: "Blue" }, { id: crypto.randomUUID(), name: "White" }, { id: crypto.randomUUID(), name: "Pink" },];
The snippet above incorrectly sets each item’s key outside the map()
method. You should avoid such a mistake!
Always set the key
prop while creating the array of elements. So, the snippet above should have set the key
on the component invocation tag—in the map()
method.
Example 2: Correct placement of the key prop
Section titled “Example 2: Correct placement of the key prop”import { createRoot } from "react-dom/client";import { bestColors } from "./bestColors.js";
function ColorListElement({ color }) { return <li>{color.name}</li>;}
function BestColor() { const bestColorsLiElements = bestColors.map((color) => ( // CORRECT: Always define the key directly inside the map() method. <ColorListElement key={color.id} color={color} /> )); return <ul>{bestColorsLiElements}</ul>;}
const root = createRoot(document.getElementById("root"));root.render(<BestColor />);
export const bestColors = [ { id: crypto.randomUUID(), name: "Blue" }, { id: crypto.randomUUID(), name: "White" }, { id: crypto.randomUUID(), name: "Pink" },];
React does not pass keys to components
Section titled “React does not pass keys to components”React neither transfers the key
prop to components nor includes it as an attribute of a rendered element.
React uses keys solely to know the state of array items. They help React identify changes to the array.
Therefore, if you need to use a specific key’s value in your component or on your DOM element, you should explicitly pass it as the value of a different attribute.
Here’s an example:
import { createRoot } from "react-dom/client";import { bestColors } from "./bestColors.js";
function ColorListElement(props) { return ( <li> {props.color.name} (ID: {props.id}) </li> );}
function BestColor() { // Use `color.id` as the `key` and `id` props' value. const bestColorsLiElements = bestColors.map((color) => ( <ColorListElement key={color.id} id={color.id} color={color} /> )); return <ul>{bestColorsLiElements}</ul>;}
const root = createRoot(document.getElementById("root"));root.render(<BestColor />);
export const bestColors = [ { id: crypto.randomUUID(), name: "Blue" }, { id: crypto.randomUUID(), name: "White" }, { id: crypto.randomUUID(), name: "Pink" },];
The snippet above initialized each list item’s id
attribute with the same value as the key
prop. By so doing, the ColorListElement
component can access props.id
but not props.key
.
Always generate the keys outside your components
Section titled “Always generate the keys outside your components”Never generate keys on the fly (while rendering your components). Instead, create them in your data outside your components. Otherwise, React will recreate the elements on every rendering cycle because the key
’s value will always be different.
Example 1: Incorrect place to generate the key prop
Section titled “Example 1: Incorrect place to generate the key prop”import { createRoot } from "react-dom/client";import { bestColors } from "./bestColors.js";
function BestColor() { // WRONG: Never generate keys on the fly. const bestColorsLiElements = bestColors.map((color) => ( <li key={crypto.randomUUID()}>{color}</li> )); return <ul>{bestColorsLiElements}</ul>;}
const root = createRoot(document.getElementById("root"));root.render(<BestColor />);
// The keys' values should have been set here (outside the component while creating your data).export const bestColors = ["Blue", "White", "Pink"];
The snippet above incorrectly generated each element’s key while rendering the BestColor
component. You should avoid such a mistake to prevent subtle bugs caused by recreating the elements on every render.
Always create each key
’s value in your data outside the component.
Example 2: Correct place to generate the key prop
Section titled “Example 2: Correct place to generate the key prop”import { createRoot } from "react-dom/client";import { bestColors } from "./bestColors.js";
function BestColor() { const bestColorsLiElements = bestColors.map((color) => ( <li key={color.id}>{color.name}</li> )); return <ul>{bestColorsLiElements}</ul>;}
const root = createRoot(document.getElementById("root"));root.render(<BestColor />);
// CORRECT: Always generate the key in your data outside the component.export const bestColors = [ { id: crypto.randomUUID(), name: "Blue" }, { id: crypto.randomUUID(), name: "White" }, { id: crypto.randomUUID(), name: "Pink" },];
The snippet above correctly generated each element’s key in the array data outside the component.