← Back to Chapters

Using Keys in React

⚛️ Using Keys in React

React Lists & Rendering

Keys are small string identifiers that make a big difference in how efficiently React updates your UI.

⚡ Quick Overview

  • Keys are special string attributes used by React to uniquely identify list items.
  • They help React figure out which items changed, were added, or removed between renders.
  • Correct keys → efficient DOM updates, fewer bugs, smoother UI.
  • Bad or missing keys → warnings in console, unexpected reordering, or incorrect updates.

? Key Concepts

  • React performs reconciliation to update the UI when state or props change.
  • During reconciliation, React compares previous and next lists using keys.
  • If a key is the same: React reuses the existing DOM node.
  • If a key is new: React creates a new DOM node.
  • If a key disappears: React removes that DOM node.
  • Keys only need to be unique among siblings, not globally unique.
  • Keys are for React’s internal use and are not available via props inside the component.

? Syntax & Theory

When rendering lists in React, you typically use Array.map() and assign a key to the element returned from the callback:

? View Code Example
// 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.

? Example 1: Number List with Keys

In this example, each list item uses the number itself as a key, which is fine because the list is simple and static.

? View Code Example
// 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.

? Example 2: Using Keys in a Todo List

For dynamic lists, always use a dedicated unique identifier such as id from your data.

? View Code Example
// 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.

? Example 3: Index vs. Stable ID

Avoid using array indexes as keys for dynamic lists. It can break component identity when the list changes.

? View Code Example
// ⚠️ 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.

? Example 4: Correct Key Placement

Keys belong on the element inside the array being iterated, not on the parent.

? View Code Example
// ✅ 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.

? Example 5: Dynamic Lists with State

Keys are essential when items are added or removed using state. Each new task must get a unique key.

? View Code Example
// 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.

? Behind the Scenes: Reconciliation

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:

  • Input values
  • Animations
  • Component state

In short, keys help React perform minimal DOM changes for smoother rendering performance.

? Live Output / Explanation

? What the User Sees vs. What React Tracks

  • In NumberList, the browser displays a simple list: 1 2 3 4 5. React uses each number as the key to keep items stable if the component re-renders.
  • In TodoList and TaskManager, adding a new item visually appends a new list entry. Internally, React uses the id-based keys to attach the right DOM node to the right task.
  • If you were to reorder or filter the list, React relies on keys to move the correct DOM nodes instead of destroying and recreating everything.

Thanks to keys, updates feel instant and smooth, while React does the minimum amount of work necessary under the hood.

? Key Best Practices

  • ✅ Use stable, unique identifiers such as database IDs or UUIDs.
  • ✅ Keep keys on the element directly returned from map() (usually a list item or component).
  • ✅ Ensure keys remain consistent across renders for the same logical item.
  • ✅ For nested data, use composite keys like {`parent.id + '-' + child.id`}.
  • ✅ Remember: keys are for React’s internal bookkeeping and are not passed as regular props.
  • ? Avoid using array indexes as keys for lists that can change order or length.
  • ? Avoid non-unique or unstable values (like random numbers on every render) as keys.
  • ? Always pay attention to “Missing key” warnings in the console—they indicate a real rendering issue.

? Tips

  • Keys help React detect and minimize DOM changes, making your UI more performant.
  • When mapping nested data, composite keys like {`parent.id + '-' + child.id`} keep each level unique.
  • Changing a key forces React to reset a component’s state—useful when you need a “fresh” instance.
  • Use tools like React DevTools and browser console warnings to spot missing or incorrect keys early.

? Try It Yourself

  1. Create a list of users and assign unique keys (like user.id) to each list item.
  2. Experiment with using indexes as keys and then reorder the list—observe how the rendered output or state behaves unexpectedly.
  3. Build a dynamic task list where each task has a unique key generated via Date.now() or a UUID.
  4. Temporarily remove keys and inspect the warnings in React DevTools or the browser console. Add the keys back and confirm the warnings are gone.

Goal: Understand how keys enable efficient rendering, maintain component identity, and how following best practices prevents subtle UI bugs in React applications.