You’ve got a list of items. Now you just need to get them on the screen.
What’s the “React way” to render a list?
The good news is it’s pretty simple. All you need is Array.map
.
The Non-React Way to Render a List
If you’re not accustomed to functional programming yet, your first inclination to render a list might be to create a new array, then iterate over the list and push JSX elements into it. Something like this:
function NonIdiomaticList(props) {
// Build an array of items
let array = [];
for(let i = 0; i < props.items.length; i++) {
array.push(
<Item key={i} item={props.items[i]} />
);
}
// Render it
return (
<div>
{array}
</div>
);
}
This works, but it’s a lot of lines of code to accomplish the task. Let me show you a better way – the idiomatic way to render a list in React.
The React Way to Render a List
This component uses Array’s built-in map
function to create a new array that has the same number of elements, and where each element is the result of calling the function you provide.
function IdiomaticReactList(props) {
return (
<div>
{props.items.map((item, index) => (
<Item key={index} item={item} />
))}
</div>
);
}
A Note on the key
Prop
You might’ve noticed I used the item’s array index as the key
prop in both examples above. This is actually not a great idea in all cases, and I’ll tell you why.
(The best choice for a key is an item’s unique ID, if it has one.)
React relies on the key
to identify items in the list. Remember React uses a virtual DOM, and it only redraws the components that changed since the last render.
The first time a component like IdiomaticReactList
is rendered, React will see that you want to render a bunch of items, and it will create DOM nodes for them.
The next time that component renders, React will say, “I already have some list items on screen – are these ones different?” It will avoid recreating DOM nodes if it can tell that the items are the same.
But here’s the important bit: React can’t tell with a simple equality check, because every time a JSX element is created, that’s a brand new object, unequal to the old one.
So that’s where the key
prop comes in. React can look at the key
and know that, yes, even though this <Item>
is not strictly ===
to the old <Item>
, it actually is the same because the key
s are the same.
This leads to a couple rules for keys. They must be:
- Unique – Every item in the list must have a unique key. So,
person.firstName
would be a bad choice, for example (might not be unique).
and
- Permanent – An item’s key must not change between re-renders, unless that item is different. So,
Math.random
is a bad choice for a key (it’ll change every time… and it might not be unique (slim chance of that, though))
Back to the problem at hand: why isn’t an item’s array index always a good choice for a key? It seems to be unique and permanent…
If you know for sure that the list of items is static, then the array index is a fine choice.
If on the other hand, the items could be reordered at some point, that will cause weird rendering bugs. If the list can be sorted, or you might replace items with new items (e.g. fetching a new list from the server), things may not render as expected. Think about what happens in those situations: a new item replaces the one at index “0”, but to React, that item is unchanged because it’s still called “0”, so it doesn’t re-render.
So the general rule is, if your list items have a unique id
property of some sort, use that as your key.
Everything Is A List
It’s been said that most web apps are just lists of things. Songs (Spotify), thoughts (Twitter), activities (Toggl).
Now you know how to render lists in React. Which sorta means you could go write any app you want, now.