Lists and Keys in React
Most web applications need to display collections of data — a list of products, a set of comments, a table of users, or a gallery of images. In React, arrays of data are rendered by transforming each item into a JSX element using JavaScript's map() method.
Keys are a required part of rendering lists. They help React identify which items have changed, been added, or been removed, making updates efficient.
Rendering a Simple List
To display a list of items, use JavaScript's built-in .map() method to convert each element of an array into a JSX element:
function FruitList() {
const fruits = ["Apple", "Banana", "Mango", "Orange"];
return (
<ul>
{fruits.map((fruit, index) => (
<li key={index}>{fruit}</li>
))}
</ul>
);
}
The .map() method loops through the fruits array. For each fruit, it returns an <li> element. The key attribute is added to each list item — this is required by React.
What Are Keys and Why Are They Required?
Keys are unique identifiers assigned to each item in a list. React uses keys internally to track which items have changed when the list updates. Without keys, React would have to re-render the entire list even when only one item changes — which is inefficient.
Think of keys like ID badges in an office. When a new employee joins, the system uses their ID badge to identify them as new and only processes their information — not everyone else's.
Using Unique IDs as Keys
Using the array index as a key (as shown above) works for static lists but is not recommended for lists that can change — items can be added, removed, or reordered. When the list changes, the index values shift, causing bugs.
The best practice is to use a unique identifier from the data itself, such as an id field from a database:
function ProductList() {
const products = [
{ id: 101, name: "Laptop", price: "$999" },
{ id: 102, name: "Phone", price: "$499" },
{ id: 103, name: "Tablet", price: "$349" },
];
return (
<ul>
{products.map((product) => (
<li key={product.id}>
<strong>{product.name}</strong> — {product.price}
</li>
))}
</ul>
);
}
Using product.id as the key ensures each item has a stable, unique identifier that does not change when the list is updated.
Rendering Lists with Components
Each item in a list can also be rendered as a separate component. This is the most scalable approach for complex list items:
function ProductCard({ name, price }) {
return (
<div>
<h4>{name}</h4>
<p>Price: {price}</p>
</div>
);
}
function ProductList() {
const products = [
{ id: 1, name: "Laptop", price: "$999" },
{ id: 2, name: "Phone", price: "$499" },
{ id: 3, name: "Tablet", price: "$349" },
];
return (
<div>
{products.map((product) => (
<ProductCard
key={product.id}
name={product.name}
price={product.price}
/>
))}
</div>
);
}
The key prop is placed on the outermost element returned in the .map() call — in this case, on <ProductCard />, not on any element inside it.
Keys Must Be Unique Among Siblings
Keys must be unique within the same list, but they do not need to be globally unique across the entire application. Two different lists can use the same key values without conflict:
// Both lists use keys 1, 2, 3 — this is perfectly fine
const categoryList = categories.map(c => <li key={c.id}>{c.name}</li>);
const productList = products.map(p => <li key={p.id}>{p.name}</li>);
Filtering a List
JavaScript's .filter() method can be combined with .map() to display only items that meet a condition:
function InStockProducts() {
const products = [
{ id: 1, name: "Laptop", inStock: true },
{ id: 2, name: "Headphones", inStock: false },
{ id: 3, name: "Keyboard", inStock: true },
{ id: 4, name: "Mouse", inStock: false },
];
const availableProducts = products.filter((p) => p.inStock);
return (
<ul>
{availableProducts.map((product) => (
<li key={product.id}>{product.name} — In Stock</li>
))}
</ul>
);
}
First, .filter() creates a new array containing only in-stock products. Then .map() renders each one as a list item.
Handling Empty Lists
It is good practice to handle the case where a list might be empty, so the user sees a helpful message instead of a blank space:
function TaskList({ tasks }) {
if (tasks.length === 0) {
return <p>No tasks found. Add a new task to get started.</p>;
}
return (
<ul>
{tasks.map((task) => (
<li key={task.id}>{task.title}</li>
))}
</ul>
);
}
Key Points
- Use the
.map()method to render arrays of data as lists of JSX elements. - Every element in a mapped list must have a
keyprop — React requires it. - Keys must be unique among sibling elements in the same list.
- Use a stable unique value (like a database ID) as the key, not the array index — especially for dynamic lists.
- The
keyprop is placed on the outermost element in the.map()callback. - Combine
.filter()and.map()to display only items matching certain criteria. - Always handle the empty state to provide a good user experience.
The next topic covers Forms in React — how to capture and manage user input using controlled components.
