key
Identify an element among its siblings so React preserves its state and DOM across reorders.
<Component key={string | number} />Parameters
| Parameter | Type | Description |
|---|---|---|
$keyoptional | string | number | A value that uniquely identifies this element among its siblings. It is read by React itself and is not passed to the component as a prop. |
Changelog
- PHP 19.0Spreading a key inside JSX props (<div {...{key}} />) warns; write key explicitly as its own attribute.
React pairs elements up between renders by their position in the parent. A key overrides that: elements with the same key in the same parent are treated as the same element, so React keeps their state and reuses their DOM node even when the order changes.
When to reach for it
- Every element returned directly from a
map()call. - Deliberate resets: change a component's key and React unmounts the old instance and mounts a fresh one with empty state.
What trips people up
Keys are scoped to the parent, not global. Two different lists can both use 1 without conflict, and a key does not have to be unique across the app.
They must also be stable. key={Math.random()}, or an id generated during render, never matches between renders, so React destroys and recreates every item each time.
The array index is what React already uses when you omit a key, so key={i} silences the warning without fixing anything: once items are inserted, removed or reordered, component state and uncontrolled DOM (focus, scroll position, typed input values) stay attached to the slot rather than to the item.
Finally, key is consumed by React and never forwarded — props.key is undefined inside the component. Pass the same value again under another name if the child needs it.
Example
When to use it
- Rendering rows from a database where each row has an id
- Clearing a draft message when the selected conversation changes
- Keeping typed input values attached to the right item when a list is sorted
- Remounting a chart component when the dataset it displays is swapped
Frequently asked questions
Why does React warn that each child in a list should have a unique key?
Because without one, React falls back to matching by position, and a reorder or deletion then re-uses the wrong component instance and DOM node. The warning appears for any element created directly inside a map() call; add a stable id from your data.
Is it ever OK to use the array index?
Yes, when the list never reorders, never has items inserted or removed in the middle, and the items hold no state — a static footer nav, for example. As soon as any of those change, the index points at a different item than it did last render.
Do keys have to be unique across the whole page?
No, only among siblings inside the same parent. Two separate lists can both use the ids 1, 2, 3 without any conflict, and reusing the same id in a different array is explicitly fine.
More examples
Resetting a component by changing its key
Typing a draft and then switching recipients clears the textarea, because the key change makes React unmount the old Editor and mount a new one. Delete key={to.id} and the same Editor instance is reused, so the half-written message follows you to the wrong person.
import { useState } from "react";
function Editor({ contact }) {
const [draft, setDraft] = useState("");
return (
<div>
<p>To: {contact.name}</p>
<textarea
value={draft}
onChange={(e) => setDraft(e.target.value)}
placeholder="Write a message"
/>
</div>
);
}
const CONTACTS = [
{ id: 1, name: "Taylor" },
{ id: 2, name: "Alice" }
];
export default function Inbox() {
const [to, setTo] = useState(CONTACTS[0]);
return (
<div>
{CONTACTS.map((c) => (
<button key={c.id} onClick={() => setTo(c)}>
{c.name}
</button>
))}
<Editor key={to.id} contact={to} />
</div>
);
}One key for several sibling elements
Each iteration produces two sibling elements, so the key has to live on something that wraps both. Fragment carries the key and then disappears, so the DOM is a flat dt/dd/dt/dd list with no wrapper divs breaking the definition-list semantics. The <>...</> shorthand cannot be used here because it accepts no attributes.
import { Fragment } from "react";
const TERMS = [
{ id: "ssr", term: "SSR", def: "Rendering the markup on the server." },
{ id: "csr", term: "CSR", def: "Rendering the markup in the browser." }
];
export default function Glossary() {
return (
<dl>
{TERMS.map((t) => (
<Fragment key={t.id}>
<dt>{t.term}</dt>
<dd>{t.def}</dd>
</Fragment>
))}
</dl>
);
}
Discussion