frontend / react / key_property.md

Key Property in React

4 interview angles 6 min read source

Key Property in React

The key prop is a special attribute that helps React identify which items have changed, been added, or been removed in lists.

Table of Contents


What is the Key Property?

The key prop is a special string attribute that React uses to identify elements in lists. It helps React track which items have changed, been added, or been removed.

Basic Usage:

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
}

Key Characteristics:

  • Unique: Each key should be unique among siblings
  • Stable: Should not change between renders
  • Predictable: Should be based on item identity, not position

Why Keys are Important

1. Efficient Reconciliation:

// Without keys - React doesn't know which items changed
function BadList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li>{item.text}</li> // No key
      ))}
    </ul>
  );
}

// With keys - React can efficiently track changes
function GoodList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.text}</li> // Has key
      ))}
    </ul>
  );
}

2. State Preservation:

function UserList({ users }) {
  return (
    <div>
      {users.map(user => (
        <UserCard
          key={user.id} // Preserves component state
          user={user}
        />
      ))}
    </div>
  );
}

function UserCard({ user }) {
  const [isExpanded, setIsExpanded] = useState(false);

  return (
    <div>
      <h3>{user.name}</h3>
      {isExpanded && <p>{user.email}</p>}
      <button onClick={() => setIsExpanded(!isExpanded)}>
        {isExpanded ? 'Hide' : 'Show'} Email
      </button>
    </div>
  );
}

3. Performance Optimization:

// React can efficiently update only changed items
const todos = [
  { id: 1, text: 'Learn React' },
  { id: 2, text: 'Build app' },
  { id: 3, text: 'Deploy' }
];

// If we add a new todo at the beginning
const newTodos = [
  { id: 4, text: 'Plan project' }, // New item
  { id: 1, text: 'Learn React' },   // Existing item
  { id: 2, text: 'Build app' },     // Existing item
  { id: 3, text: 'Deploy' }         // Existing item
];

// React knows to only create the new element, not re-render existing ones

Best Practices

1. Use Stable IDs:

// Good: Use unique, stable IDs
function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.text}</li>
      ))}
    </ul>
  );
}

// Good: Use unique identifiers
function UserList({ users }) {
  return (
    <ul>
      {users.map(user => (
        <li key={user.email}>{user.name}</li>
      ))}
    </ul>
  );
}

2. Avoid Array Index:

// Bad: Using array index as key
function BadList({ items }) {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={index}>{item.text}</li> // Unstable key
      ))}
    </ul>
  );
}

// Good: Use stable identifiers
function GoodList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.text}</li> // Stable key
      ))}
    </ul>
  );
}

3. Generate Keys for Dynamic Lists:

// Good: Generate unique keys
function DynamicList({ items }) {
  return (
    <ul>
      {items.map((item, index) => (
        <li key={`${item.type}-${item.id}-${index}`}>
          {item.text}
        </li>
      ))}
    </ul>
  );
}

// Good: Use timestamp + random for truly unique keys
function UniqueList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={`${Date.now()}-${Math.random()}`}>
          {item.text}
        </li>
      ))}
    </ul>
  );
}

4. Keys in Nested Lists:

function NestedList({ categories }) {
  return (
    <div>
      {categories.map(category => (
        <div key={category.id}>
          <h2>{category.name}</h2>
          <ul>
            {category.items.map(item => (
              <li key={`${category.id}-${item.id}`}>
                {item.name}
              </li>
            ))}
          </ul>
        </div>
      ))}
    </div>
  );
}

Common Mistakes

1. Using Index as Key:

// Problem: Index changes when items are reordered
const items = ['Apple', 'Banana', 'Cherry'];

// Initial render
items.map((item, index) => <li key={index}>{item}</li>);
// Renders: key="0" -> Apple, key="1" -> Banana, key="2" -> Cherry

// After removing first item
items = ['Banana', 'Cherry'];
items.map((item, index) => <li key={index}>{item}</li>);
// Renders: key="0" -> Banana, key="1" -> Cherry
// React thinks Banana changed from "Apple" to "Banana"

2. Using Random Values:

// Problem: New key on every render
function BadList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={Math.random()}>{item.text}</li> // New key every time
      ))}
    </ul>
  );
}

// Solution: Use stable identifiers
function GoodList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.text}</li> // Stable key
      ))}
    </ul>
  );
}

3. Missing Keys:

// Problem: React warning and inefficient updates
function BadList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li>{item.text}</li> // No key
      ))}
    </ul>
  );
}

// Solution: Always provide keys
function GoodList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.text}</li> // Has key
      ))}
    </ul>
  );
}

4. Non-Unique Keys:

// Problem: Duplicate keys
function BadList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key="item">{item.text}</li> // Same key for all items
      ))}
    </ul>
  );
}

// Solution: Unique keys
function GoodList({ items }) {
  return (
    <ul>
      {items.map(item => (
        <li key={item.id}>{item.text}</li> // Unique key
      ))}
    </ul>
  );
}

Common Interview Questions

Q: What is the key prop in React?

  • A special attribute that helps React identify which items have changed, been added, or been removed in lists.

Q: Why are keys important in React?

  • They help React efficiently track and update list items, preserve component state, and optimize performance.

Q: What happens if you don’t provide a key?

  • React will use array index as key, which can cause issues with state preservation and inefficient updates.

Q: Can you use array index as a key?

  • It’s not recommended because it can cause issues when items are reordered, added, or removed from the list.

Q: What makes a good key?

  • Unique, stable, and predictable identifiers that don’t change between renders.

Q: How do keys help with performance?

  • They allow React to efficiently update only the items that have changed instead of re-rendering the entire list.

Q: What happens if you use duplicate keys?

  • React will warn about duplicate keys and may not work correctly with state preservation.

Summary

  • Keys help React identify and track list items efficiently
  • Unique and stable keys are essential for proper reconciliation
  • Avoid array index as keys when items can be reordered
  • Use stable identifiers like database IDs or unique properties
  • Keys preserve component state when items are reordered
  • Missing keys cause React warnings and inefficient updates
  • Duplicate keys can cause unexpected behavior
  • Keys are crucial for performance optimization in dynamic lists

Interview angle

  • “What does key do?” - gives an element a stable identity across renders so reconciliation can match, move and preserve state instead of destroying and rebuilding. It is a hint to React, never readable as a prop.
  • “Why are index keys dangerous?” - they are positional. Insert at the front, delete, or reorder, and React matches item 0 to a different item: DOM state such as input text, focus and scroll position sticks to the wrong row. Index keys are only safe for a list that is static and never reordered or filtered.
  • “How do you deliberately reset state?” - change the key. Giving a component key={userId} remounts it when the user changes, which is the cleanest way to clear internal state without an effect.
  • “Must keys be globally unique?” - only among siblings.