Chapter 17: Rendering Lists
Core Idea
Lists of components are built with plain JavaScript array methods — filter() to narrow the data, map() to turn each item into JSX — and every resulting element needs a key so React can track identity across re-renders.
Key Concepts
map() transforms data into JSX: people.map(person => <li key={person.id}>{person.name}</li>), then render the resulting array directly (<ul>{listItems}</ul>).
filter() narrows first: chain array.filter(test).map(toJSX) when you only want to render a subset — filter runs first to produce a smaller array, then map converts it.
- The missing-key console warning ("Each child in a list should have a unique 'key' prop") appears the moment you render an array of JSX without keys — it's not optional decoration.
- What makes a good key: a stable, unique-among-siblings identifier — normally an ID already present in the data (a database ID), not something generated during render.
- Why keys matter: React uses the key to match each array item across renders, so it can tell "this is the same logical item, just reordered/updated" apart from "this is a new item" — that distinction drives correct state preservation, list-item animations, and DOM reuse.
- Array index as key is a common but risky shortcut: it happens to work if the list never reorders/inserts/deletes, but breaks (misapplied state, wrong item highlighted) the moment items move — prefer a real data ID whenever one exists.
- Keys must be unique only among siblings, not globally across the whole app — the same key value can reappear in a different array elsewhere without conflict.
Code Examples
const chemists = people.filter(person => person.profession === 'chemist');
const listItems = chemists.map(person => (
<li key={person.id}>
<b>{person.name}</b> — {person.profession}
</li>
));
return <ul>{listItems}</ul>;
- What it demonstrates: the standard filter → map → render pipeline, with
key={person.id} sourced from the data itself rather than the array position.
Key Takeaways
- Treat the missing-key warning as a correctness bug to fix immediately, not console noise to ignore.
- Default to a stable data ID for
key; only fall back to index when the list is provably static (never reordered, filtered, or spliced).
filter() then map() is the idiomatic two-step pipeline for "show a subset of this data as components" — resist the urge to do both in one pass unless performance profiling justifies it.
Connects To
- Ch 16 (Conditional Rendering): the sibling JS-native technique for branching what renders.
- Ch 30 (Preserving and Resetting State): exactly how
key determines whether React preserves or resets a list item's internal state.