Skip to content

The key prop: the cheapest state reset in React

key isn't just for lists. Change it and React throws the component away and mounts a fresh one — state included. No useEffect required.

Author
Jan Jarčík
Published
Reading time
2 min read
Updated
ShareXLinkedInBluesky

Know this pattern? A form component receives a new userId and you reset its state by hand in a useEffect:

TSX
function ProfileEditor({ userId }: { userId: string }) {
  const [draft, setDraft] = useState("");
  useEffect(() => {
    setDraft(""); // ❌ extra render and a flash of stale data
  }, [userId]);
  // …
}

It works, but the component first renders with the old state and only then with the new one. And every new piece of state adds another line to the effect.

The fix: key

TSX
<ProfileEditor key={userId} userId={userId} />

React identifies components by type and position in the tree. key is part of that identity. When it changes, React unmounts the old instance and mounts a new one — with brand-new state, refs and effects. Inside ProfileEditor you don't need any reset at all.

Keys in lists

For the same reason, don't use the array index as key when items can be reordered, removed or inserted anywhere but the end:

TSX
// ❌ after deleting the first item, input state "shifts"
{todos.map((todo, i) => <TodoRow key={i} todo={todo} />)}
 
// ✅ stable identity
{todos.map((todo) => <TodoRow key={todo.id} todo={todo} />)}

With an index, React thinks row #0 is still the same row — just with different props. Local state (a half-typed text, an open menu) stays attached to the wrong item.

When key isn't enough

If you want to reset only part of the state, or need to keep something expensive (like loaded images), derive the state during render or lift it up. But eight times out of ten, key is the simplest and most readable solution.