Lists & keys
Render arrays with map, choose good keys, filter and sort — plus a first look at effects.
Most UIs display collections: lessons in a course, products in a shop, messages in a chat. In React you turn arrays of data into arrays of elements with map, and give each element a key so React can keep track of it. At the end of this lesson you'll also take a first look at effects, which you'll study in depth in the next module.
Rendering lists with map#
JSX can render arrays, so the idiomatic way to show a list is to map data to elements:
lessons.map(...) returns an array of <li> elements, which React renders in order. Remember: an arrow function with parentheses (lesson) => ( ... ) returns the JSX automatically; with braces you need an explicit return.
Extracting an item component
When each item gets complex, give it its own component — and put the key on the component in the map, not inside it:
key is special: React uses it, and it is not passed to your component as a prop.
Keys#
Every item in a list needs a key that is:
- Unique among its siblings (keys only need to be unique within one list), and
- Stable — the same item gets the same key on every render.
Forget the key and React warns in the console: Each child in a list should have a unique "key" prop.
Why index keys cause bugs
Keys tell React which item is which. With index keys, if you insert an item at the top, every item's key shifts — React thinks item 0 changed rather than that a new item appeared. Any state inside the items (an input's text, a checkbox, an animation) stays attached to the wrong row:
Type a note next to "Ada", then click the button. With key={index}, your note jumps to "Grace" (now at index 0). With key={p.id}, it stays with Ada. If your data has no ids, generate them when you create the data (e.g. crypto.randomUUID() when adding an item), never during render.
Fragments with keys
To render several elements per item without a wrapper, use Fragment with a key:
Filtering and sorting before rendering#
Prepare the data with array methods, then map:
Notice that visible is derived during render, not stored in state — it's always in sync with query and sortBy. Use toSorted (or [...arr].sort()) so you never mutate the original array.
Nested lists#
Each inner list has its own key scope, so two modules could both contain a lesson keyed "intro" without a clash.
A first look at effects#
Rendering must be pure: compute JSX from props and state, nothing else. But sometimes a component needs to synchronise with something outside React — the page title, a timer, a network request, a browser API. That's what useEffect is for. It runs your code after React has updated the screen:
The second argument is the dependency array: React re-runs the effect only when one of these values has changed since the last render.
Effects can also return a cleanup function, which React calls before re-running the effect and when the component is removed:
That's enough to get started. The useEffect & the component lifecycle lesson covers dependency arrays, cleanup, Strict Mode's double-run and — importantly — when you don't need an effect.
Common mistakes#
- Forgetting the
key, or putting it on the wrong element (it goes on the outermost element returned frommap). - Using array indexes as keys for lists that change.
- Generating keys with
Math.random()during render. - Sorting state in place with
.sort()— that mutates it. UsetoSorted. - Storing filtered or sorted copies in state instead of deriving them.
What's next#
Lists and keys done. Next, collect user input properly with forms and controlled inputs.
Check your understanding
Quick quiz
1.Why does React need a
keyon list items?2.Which is the best key for a list of products from an API?
3.When does
useEffect(fn, [])runfn?
Finished reading?
Mark this lesson complete to track your progress.