React Lists & Rendering
Keys are small string identifiers that make a big difference in how efficiently React updates your UI.
When rendering lists in React, you typically use Array.map() and assign a key to the element returned from the callback:
// Basic pattern: map over an array and add keys
const items = [
{ id: 1, label: "Item A" },
{ id: 2, label: "Item B" },
];
function ItemList() {
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.label}</li>
))}
</ul>
);
}
Here, item.id is a stable and unique identifier, making it a perfect choice for the key.
In this example, each list item uses the number itself as a key, which is fine because the list is simple and static.
// Renders a list of numbers with keys for each item
function NumberList() {
const numbers = [1, 2, 3, 4, 5];
return (
<ul>
{numbers.map((n) => (
<li key={n}>{n}</li>
))}
</ul>
);
}
Since each number is unique and the list is not reordered, using n as the key is safe here.
For dynamic lists, always use a dedicated unique identifier such as id from your data.
// Todo list with stable IDs used as keys
function TodoList() {
const todos = [
{ id: 101, task: "Study React" },
{ id: 102, task: "Write Code" },
{ id: 103, task: "Read Docs" },
];
return (
<ul>
{todos.map((item) => (
<li key={item.id}>{item.task}</li>
))}
</ul>
);
}
Using item.id as the key allows React to track each todo accurately, even if items are added, removed, or reordered.
Avoid using array indexes as keys for dynamic lists. It can break component identity when the list changes.
// ⚠️ Using index as key can cause issues when order changes
{items.map((item, index) => (
<li key={index}>{item.name}</li>
))}
// ✅ Better: use a stable unique ID for each item
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
Index keys are only safe for static lists that never change order or content. For dynamic data, always prefer a stable ID.
Keys belong on the element inside the array being iterated, not on the parent.
// ✅ Correct: key on the <li> returned from map()
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
// ❌ Wrong: key on the parent <ul> instead of list items
<ul key="list">
{users.map((u) => (
<li>{u.name}</li>
))}
</ul>
React needs the key on each repeated child element so it can track them individually.
Keys are essential when items are added or removed using state. Each new task must get a unique key.
// Task manager that adds items with unique keys
import { useState } from "react";
function TaskManager() {
const [tasks, setTasks] = useState([
{ id: 1, name: "Complete project" },
{ id: 2, name: "Review PR" },
]);
const addTask = () => {
const newTask = { id: Date.now(), name: "New Task" };
setTasks([...tasks, newTask]);
};
return (
<div>
<ul>
{tasks.map((t) => (
<li key={t.id}>{t.name}</li>
))}
</ul>
<button className="btn btn-primary" onClick={addTask}>
Add Task
</button>
</div>
);
}
Here, Date.now() is used to generate a unique key for each new task at the moment it’s created.
React maintains a Virtual DOM and uses keys during the diffing process to match elements between renders.
With correct keys, React reuses components efficiently instead of recreating them from scratch. This avoids unnecessary unmounts and remounts, preserving:
In short, keys help React perform minimal DOM changes for smoother rendering performance.
1 2 3 4 5. React uses each number as the key to keep items stable if the component re-renders.id-based keys to attach the right DOM node to the right task.Thanks to keys, updates feel instant and smooth, while React does the minimum amount of work necessary under the hood.
map() (usually a list item or component).{`parent.id + '-' + child.id`}.{`parent.id + '-' + child.id`} keep each level unique.user.id) to each list item.Date.now() or a UUID.Goal: Understand how keys enable efficient rendering, maintain component identity, and how following best practices prevents subtle UI bugs in React applications.