Rendering a list of shows
Turn an array of shows into cards with map, and give React a key it can trust.
App has three ShowCard lines typed out by hand, so a fourth show means a
fourth line. The data should decide how many cards there are.
There is no loop in JSX
JSX has no loop. You turn an array of data into an array of elements with
map, and JSX renders an array.
The first map gives three strings, and JSX puts them next to each other with
nothing in between, so they read as The BearSeveranceAndor. The second map
gives three elements, so you get three rows.
Note the round brackets after the arrow. (show) => (<li>...</li>) returns the
element. Curly brackets there would be a function body that returns nothing —
the trap from Arrow Functions and this.
Each <li> also has a key. That is the next section.
Keys tell React which row is which
On every render React compares the new list with the old one, so it can tell
what moved, what was added, and what has gone. The key is how it matches them
up. A key must be unique among its brothers and sisters in the same list, and
it must stay the same for the same item on every render.
key={index} looks like the easy answer. The button below uses useState,
which Marking a show as watched covers, so ignore how it works. Type a note
in the first box of each list, then press the button.
In the left panel your note stays in the top box, and the top box now belongs to Andor. In the right panel the note moves down with The Bear, where you put it.
Your text is not in shows anywhere. It lives in the input, and React decides
which input to keep by key. With key={index} the first row is always key 0,
so React keeps that box for whatever show is first now. With key={show.id}
React knows The Bear moved, and moves its box with it.
Choosing a key
- An id from your data is the one to use: it belongs to the item and never changes.
- The index is a position, not an item, so it points at a different show the moment the list changes.
- The title can repeat, and it changes when you fix a typo. So can any other value on the screen.
Math.random()gives a new key every render, so React throws every row away and builds it again.
One show object, one card
map hands you one show at a time, so the natural thing to pass is that whole
show: <ShowCard show={show} />. That is the shape
Passing props to a card tried out on a small example, and the
app takes it now.
Each show gets an id as well, to key on.
The page looks exactly as it did before. What changed is where the shows live:
add a fourth one to the array and a fourth card appears, with no new markup.
Arrays are Working with Arrays, and map is
Array Methods.
Common mistakes
- Curly brackets in the callback with no
return.(show) => { ... }is a function body, so withoutreturnit gives back nothing and the list is empty, with no error shown. keyon the wrong element. It goes on the element themapreturns, not on something inside it.- Reading
keyas a prop.keyis for React, and the component cannot see it. Passidas its own prop if the component needs the value.
Exercise
The page is blank. Nothing throws, and nothing is drawn. There is a second thing to fix that the page will not tell you about: the mapped element has no key.
Fix both so the page reads:
Three cards side by side. The Bear, Drama, 2022 · ★ 8.6. Severance,
Thriller, 2022 · ★ 8.7. Andor, Sci-Fi, 2022 · ★ 8.4. Each card has a
title above its year.
Hint: look at what the callback gives back, and at what each show has that no other show has.