When rendering arrays in React, key is how React tracks which item is which between renders. Without a proper key, React can reuse the wrong DOM nodes when items are removed or reordered.
keyThe key prop helps React identify which items have changed, been added, removed, or reordered between renders.
const fruits = [{ id: "a1", name: "Apple" },{ id: "b2", name: "Banana" },{ id: "c3", name: "Cherry" },];function FruitList() {return fruits.map((fruit) => (<div key={fruit.id}>{fruit.name}</div>));}
Why use stable keys?
What happens without keys?
React may use positional matching when keys are missing, which can cause stateful DOM elements to be reused in unexpected ways when items are removed or reordered.
For example, an uncontrolled input may retain the text entered for a different fruit after deleting an item.
Best practice: Use a stable, unique ID from your data. Avoid array indexes when the list can be reordered, inserted into, or deleted from.
key to Reset StateChanging a component’s key tells React to treat it as a different component identity, causing the previous instance to be removed and a new one to be mounted.
import { useState } from "react";function FruitInput() {const [resetKey, setResetKey] = useState(0);return (<><input key={resetKey} defaultValue="Apple" /><button onClick={() => setResetKey((key) => key + 1)}>Reset</button></>);}
When the button is clicked, React remounts the input with its initial value.
Important: Remounting also resets the element’s focus and selection and discards its previous DOM state. For controlled inputs, the displayed value is determined by React state, so changing the key alone does not reset that state.
Try typing different text into each input, then remove the first fruit. Compare index-based keys with stable IDs.
Bug: Using the array index as the key
{items.map((fruit, index) => (<div key={index}><input defaultValue={fruit.name} /><buttononClick={() =>setItems((prev) =>prev.filter((item) => item.id !== fruit.id))}>Remove</button></div>))}
Reproduce the bug:
My Apple into the Apple input.My Banana into the Banana input.My Apple because React reuses the DOM input previously associated with index 0.Fix: Use a stable ID
{items.map((fruit) => (<div key={fruit.id}><input defaultValue={fruit.name} /><buttononClick={() =>setItems((prev) =>prev.filter((item) => item.id !== fruit.id))}>Remove</button></div>))}
With stable IDs, React can correctly associate each input with its fruit when the list changes.