WebMriya
Back to articles

React Keys Define Component Identity

Learn why React keys define component identity, how unstable keys cause state bugs, and how to choose safe keys for dynamic lists and forms.

React
TypeScript
Frontend Architecture
W
Frontend Architecture & Legacy Modernization
October 16, 2026 · 5 min read

A user edits the second row in a list, removes the first row, and suddenly the remaining row shows the wrong value. The code looks ordinary: map over an array, render a component, add a key. Yet the key is an array index, so React treats a position as an identity. Once the list changes, component state can follow the position instead of the data.

Keys are often treated as a way to silence a console warning. They do more than that: a key helps React decide which rendered component corresponds to which item between renders. That decision affects whether React preserves a component instance and its local state, or unmounts it and creates another. Understanding keys as identity makes a class of confusing UI bugs much easier to prevent.

A key is part of component identity

React reconciles the previous tree with the next one. For sibling elements, it uses their type, position, and key to match components. When the type and key remain stable, React can reuse the existing component and preserve its state. When the key changes, React treats the element as a different identity: the old component is discarded, and a new one mounts.

This is why keys matter for more than rendering efficiency. A row may contain an uncontrolled input, a focused element, an expanded menu, a draft, or state managed by a child component. If React associates that state with the wrong item after a reorder, the interface can remain valid HTML while showing the wrong user data.

Why array indexes fail in dynamic lists

An index describes where an item happens to be now, not which item it is. If an item is inserted, removed, filtered, or moved, the indexes of other items change. React can then reuse the component at position one for a different record, preserving local state that belonged to the previous record.

tsx
type Row = { id: string; name: string };

function Rows({ rows }: { rows: Row[] }) {
  return rows.map((row, index) => (
    <EditableRow key={index} row={row} />
  ));
}

The example becomes risky as soon as rows can change order or membership and EditableRow has its own state. For a fixed list of purely presentational items that never changes, an index can be acceptable. The problem is not the syntax itself; it is using a position as identity when position is allowed to change.

Choose a stable key from the data

Prefer a stable identifier that belongs to the record and stays the same as it moves through the UI. Database IDs are a natural choice. If a new record does not have a server ID yet, create a client-side ID when the record is created—not inside render—and keep it with that record.

tsx
function Rows({ rows }: { rows: Row[] }) {
  return rows.map((row) => (
    <EditableRow key={row.id} row={row} />
  ));
}

A key only needs to be unique among siblings in the same rendered list. It does not need to be globally unique across the entire application. But it must be stable across renders for the same logical item. A useful test is: if this item moves to another position, can I still derive the same key from the item itself?

Common key choices and their trade-offs

Key choiceUsually safe whenMain risk
Persistent record IDThe ID belongs to the item and does not changeA missing or reused ID can match different records
Client-generated IDIt is created once and stored with the new itemGenerating it during render changes identity every time
Array indexThe list is static and cannot reorder, insert, or remove itemsState may stick to a position instead of its record
Random value during renderAlmost neverEvery render remounts the item and discards its local state

Composite keys can be useful when a single stable field is not unique. Combine stable fields that together identify the record, and make sure the combination cannot collide. Avoid including values that change during editing: when a key changes, React remounts the component, potentially clearing focus and unsaved input state.

Keys can intentionally reset state

A changed key is not always a mistake. It is a direct way to tell React that a component represents a new identity and its previous local state should not be preserved. For example, a profile editor might reuse the same component for different user IDs. Keying the editor by user ID can ensure that a draft for one user does not appear when viewing another.

Use this deliberately, not as a general fix for state that feels stale. First identify which component owns the state and what event should reset it. If a key based on a user ID is right, the state reset is explicit and connected to an identity change. If a key is derived from a changing input value, it may instead cause a remount on every keystroke.

Keys matter in forms and nested lists

Dynamic forms are particularly sensitive because each row can contain values, validation messages, and focus state. Removing one field should remove that field's state—not transfer it to the next field. A stable field ID is safer than its current array position. The same principle applies to nested lists: each mapped collection needs stable keys for its own sibling elements.

For more on keeping growing forms predictable, see React Forms Without State Sprawl. If the interface has multiple interacting states, React State Machines: Replace Boolean Flags With Explicit UI States discusses another way to make transitions clear. These concerns are related, but distinct: a state model defines what the UI can do; a key helps React keep the right component state attached to the right item.

A practical review checklist

  1. Find every mapped collection that can change after the initial render.
  2. Check whether each key comes from the record, rather than its current position.
  3. Verify that the same logical record keeps the same key after insertion, deletion, filtering, or sorting.
  4. Check that keys are unique among siblings, including when records are created locally.
  5. Look for keys that change during editing or are generated randomly during render.
  6. Test by editing a row, then inserting, removing, sorting, and filtering neighboring rows.

When a test shows state moving to the wrong row, start by inspecting identity rather than adding more effects or copying values into another state store. A stable key often fixes the association at its source. If the behavior persists, check whether the component type also changes between renders and whether another layer is resetting its state.

Keys are a small part of React code with a large effect on the behavior of dynamic interfaces. Choosing them from stable domain identity—not from convenient render position—helps keep drafts, inputs, focus, and child state aligned with the data users expect. For teams building data-rich interfaces with changing lists and complex forms, WebMriya's complex application development can support the architecture and implementation work.

Frequently asked questions

Why is using an array index as a React key risky?

Indexes change when items are inserted, removed, or reordered. React may then preserve a component's state for a different record than the one it originally belonged to.

Does a React key need to be unique across the whole application?

No. A key needs to be unique among the sibling elements in the same rendered list. It should also remain stable for the same logical item across renders.

Can changing a key reset a component's state?

Yes. A new key tells React that the component has a different identity, so it unmounts the previous instance and mounts a new one. This can be useful when the identity truly changes, but accidental key changes can discard drafts or focus.