Lists are everywhere, and wrong keys cause subtle bugs where state sticks to the wrong row.
To render a list, transform your data array into an array of JSX elements, usually with map, and filter first with filter if needed:
const items = people
.filter(p => p.active)
.map(p => <li key={p.id}>{p.name}</li>);
return <ul>{items}</ul>;Every element in an array needs a `key` prop: a string or number that uniquely identifies that item among its siblings. Keys tell React which item is which between renders. When you insert, delete or reorder items, React uses keys to move the existing DOM nodes and component state along with the right data instead of rebuilding everything or, worse, pairing state with the wrong item.
Good keys come from the data: database ids, slugs, or ids you generate once when the item is created (crypto.randomUUID()). Rules:
- Keys must be unique among siblings, not globally.
- Keys must be stable: the same item gets the same key on every render.
- Don't use the array index if the list can be reordered, filtered or have items inserted; the index then refers to a different item and any state (like a typed-in input) follows the position, not the item. Index is acceptable only for static lists.
- Never generate keys during render (
key={Math.random()}); every render then creates brand-new components.
The key goes on the outermost element returned from map. If you need to return several elements per item, use <Fragment key={id}> (import Fragment from react), since the short <> syntax can't take a key.
Keys are not passed to your component as a prop; pass the id separately if the child needs it.
Example
import { Fragment } from "react";
const people = [
{ id: "a1", name: "Creola Johnson", profession: "chemist" },
{ id: "b2", name: "Mario Molina", profession: "chemist" },
{ id: "c3", name: "Percy Julian", profession: "chemist" },
{ id: "d4", name: "Subrahmanyan Chandrasekhar", profession: "astrophysicist" },
];
export default function Scientists() {
const chemists = people.filter(p => p.profession === "chemist");
return (
<dl>
{chemists.map(p => (
// several elements per item: keyed Fragment
<Fragment key={p.id}>
<dt>{p.name}</dt>
<dd>{p.profession}</dd>
</Fragment>
))}
</dl>
);
}Remember
- Render arrays with
map(andfilter); each element needs akey - Keys must be unique among siblings and stable across renders, ideally ids from the data
- Avoid index keys for lists that change order or contents; never use random keys
Watch out for
- Using the array index as key in an editable or sortable list, so input state ends up on the wrong row.