React & State · T116

Why did my checkbox move?

Index keys identify positions. After sorting, React can keep a row’s local checked state while that position now represents a different item.

The important bit
Use stable item IDs. Random keys reset state. Index keys can fit fixed lists whose items never change position or identity.

Understand it. Then fix it.

Index keys identify the position.

Your keys are array indexes: zero and one. After sorting, key zero still exists, but now it shows salad. React keeps that row component and its checked state.

items.map((item, index) => (
  <Row key={index} item={item} />
))

Exactly. The state lives in each Row.

Exactly. This row owns checked in useState. A new item prop does not reset that state. With index keys, the same position can represent a different item.

function Row({ item }) {
  const [checked, setChecked] =
    useState(false);
  // Checkbox uses checked.
  // Label uses item.name.
}

Use the item ID. Keep its identity.

Use a stable ID from the item instead. Now React matches the pizza row with pizza after sorting. Its checked state moves with it.

items.map(item => (
  <Row key={item.id} item={item} />
))

Stable means not made during render.

Do not create random keys during rendering. New keys create new rows and reset state. Index keys can fit a fixed list whose items never change position or identity.

Code blocks are teaching excerpts. Keep the surrounding error handling and application requirements.

Save the code excerpts ↓
Read the full transcript

In my React list, I check pizza and sort the rows. Now salad is checked. Who changed my lunch? Your keys are array indexes: zero and one. After sorting, key zero still exists, but now it shows salad. React keeps that row component and its checked state. So the checkbox did not follow the food. The first row kept its state and got a different label? Exactly. This row owns checked in useState. A new item prop does not reset that state. With index keys, the same position can represent a different item. Use a stable ID from the item instead. Now React matches the pizza row with pizza after sorting. Its checked state moves with it. Do not create random keys during rendering. New keys create new rows and reset state. Index keys can fit a fixed list whose items never change position or identity. My app changed my lunch without asking. Even my bugs think I should eat a salad.

Go to the source