Lists and Keys

Course 1 · Ch 6
Lists and Keys
Turning an array of data into repeated JSX, and why React needs a key to track each piece

Real applications display arrays of things constantly — a list of todos, search results, products in a cart. React has no special "repeat this markup" tag; instead, you use a regular JavaScript array method, .map(), to transform an array of data into an array of JSX elements.

Rendering an Array with .map()

function FruitList() { const fruits = ["Apple", "Banana", "Cherry"]; return ( <ul> {fruits.map((fruit) => ( <li key={fruit}>{fruit}</li> ))} </ul> ); }

fruits.map(fruit => <li>...</li>) produces a new array, this time of <li> elements instead of strings — and React happily renders an array of elements embedded inside { } exactly like it renders a single one. The curly braces around the whole .map() call work the same way they always have: dropping back into JavaScript inside JSX.

The key Prop — Why It's Required

Every element produced inside a .map() needs a unique key prop, as seen above. React uses keys to match each element in a new render against the same element from the previous render — without them, React can only guess by position, which causes real bugs when items are reordered, inserted, or removed (state belonging to one item can end up incorrectly attached to a different one after the list changes).

const todos = [ { id: 1, text: "Buy milk" }, { id: 2, text: "Walk the dog" }, ]; function TodoList() { return ( <ul> {todos.map((todo) => ( <li key={todo.id}>{todo.text}</li> ))} </ul> ); }

A genuinely stable, unique identifier — like a database id — makes the best key. The plain string array example above used the fruit name itself only because the list had no duplicates and no id field available; a real dataset with an id field should always prefer it over anything else.

Don't use the array index as a key (when avoidable)
fruits.map((fruit, index) => <li key={index}>...) silences React's missing-key warning but doesn't actually solve the underlying problem — if the array's order changes, the index stays attached to a position rather than to the actual item, causing the exact same bugs keys exist to prevent. It's an acceptable last resort only for lists that are genuinely static and never reordered/filtered.

Rendering a Full Component Per Item

function TodoItem({ text }) { return <li>{text}</li>; } function TodoList() { return ( <ul> {todos.map((todo) => ( <TodoItem key={todo.id} text={todo.text} /> ))} </ul> ); }

The same pattern extends naturally to rendering a custom component per item instead of a plain <li> — the key still goes directly on the outermost element returned from .map() (here, the <TodoItem /> tag itself), never on something nested inside that component.

Filtering Before Rendering

function ActiveTodos({ todos }) { return ( <ul> {todos .filter((todo) => !todo.done) .map((todo) => <li key={todo.id}>{todo.text}</li>)} </ul> ); }

Because .map() is just a regular array method, it chains naturally with .filter(), .sort(), or anything else from the array toolbox — filter down to the items that should actually be shown first, then map the remaining ones to JSX.

key is invisible to the component itself
A component can't read its own key as a prop (props.key is always undefined) — it's reserved exclusively for React's internal bookkeeping. If a component also needs that same value for its own logic, pass it again under a different prop name, as TodoItem's separate text prop did above.
Key sourceQuality
Database idBest — stable and unique regardless of order changes
A unique field (email, slug)Good, as long as it's genuinely unique in the dataset
Array indexLast resort only — breaks if the list is reordered/filtered

Coding Challenges

Challenge 1

Given an array of at least 4 city name strings, render them as an unordered list using .map(), using each city name itself as the key.

📄 View solution
Challenge 2

Given an array of objects like { id, name, price }, render each one as a div showing "name — $price", using id as the key.

📄 View solution
Challenge 3

Given an array of objects like { id, name, inStock: true/false }, filter to only the in-stock items before mapping them to a list, so out-of-stock items never appear at all.

📄 View solution

Chapter 6 Quick Reference

  • .map() — the standard way to turn an array of data into an array of JSX elements
  • Every mapped element needs a unique key prop, on the outermost returned element
  • Prefer a stable id over the array index as a key whenever one is available
  • key is reserved for React — a component can't read its own props.key
  • .filter() chains naturally before .map() to exclude items from rendering entirely
  • Next chapter: forms and controlled inputs — managing a form's fields properly with state