Rendering Lists
Rendering a list is just .map() turning data into elements. The interesting part isn't the map — it's key, and why React demands it.
Map data to elements
An array of elements drops straight into JSX, because React renders each item in an array.
function ProductList({ products }) {
return (
<ul>
{products.map((p) => (
<li key={p.id}>{p.name}</li>
))}
</ul>
);
}
Filter first, then map
No special syntax for "only some" — I filter the array, then map what's left. Both are just JS.
{users
.filter((u) => u.isActive)
.map((u) => <UserRow key={u.id} user={u} />)}
Keys — what they're actually for
A key isn't decoration and it isn't for me — it's how React identifies which item is which across renders. When the list changes, React matches old elements to new ones by key, so it knows what moved, what's new, and what to leave alone. Get the key right and React reuses DOM nodes and component state correctly; get it wrong and it quietly mixes them up.
Don't use the array index as a key when the list can reorder, filter, or have items inserted. The index describes a position, not an item — so when things shift, React thinks item #2 is still item #2 and hands the wrong state (input values, focus, animation) to the wrong row.
{items.map((item, i) => <Row key={i} item={item} />)} // reorders → state leaks between rows
{items.map((item) => <Row key={item.id} item={item} />)} // stable identity, correct
Index is only fine for a list that never changes order and never grows or shrinks.
A key has to be stable (same item → same key every render) and unique among siblings. That's it — it doesn't need to be globally unique, and I never generate it inside render (key={Math.random()} gives a new key every time, so React rebuilds every row from scratch).
When each item needs multiple tags
If a single item renders more than one node, I can't put the key on a wrapping <div> I don't want — I use a <Fragment> with the key. The <>…</> shorthand can't take a key, so this is the one place I write it out.
import { Fragment } from "react";
{terms.map((t) => (
<Fragment key={t.id}>
<dt>{t.name}</dt>
<dd>{t.definition}</dd>
</Fragment>
))}