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.
Know this pattern? A form component receives a new userId and you reset its state by hand in a useEffect:
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
<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:
// ❌ 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.