List Rendering
By Syncfusion®, Inc. · Last updated
Rendering lists with map(), showing arrays of objects, filtering, what keys are and why they matter, and nested lists.
What Are Lists?
A list is a group of items shown one after another, such as books in a shop, messages in a chat, or rows in a table.
In React, the data for a list is usually stored in an array. You turn each item in the array into a piece of TSX. This is called list rendering.
Real-World Example
A bookshop app receives an array of 50 books from the server. The component writes books.map(book => <BookCard key={book.id} book={book} />) once.
React creates one card for each book. When a book is removed from the array, React uses the key to remove only that card from the page.
You do not write each list item by hand. You keep the data in an array, and React makes one element for each item.
Rendering Lists with map()
map() is a JavaScript array method. It goes through each item in an array, runs a function on it, and gives back a new array with the results.
In React, you use map() to turn an array of data into an array of TSX elements.
Animation: map goes through the books array and turns each item into an li element books (array of data)<li> elements on the page"The Alchemist"<li>The Alchemist</li>"Wings of Fire"<li>Wings of Fire</li>"Atomic Habits"<li>Atomic Habits</li>books.map(book => <li>)
map() runs once for each item and returns one <li> per book.
Look at this line:
{books.map((book) => <li key={book}>{book}</li>)}
It means: for each book in the books array, make an <li> that shows the book's name. The key part is explained later in this lesson.
Add a fourth book to the array and press ▶ Run. A fourth list item appears, without any other change.
Dynamic Data Rendering
Real data is usually an array of objects, not just names. Each object has several fields, such as a title, an author and a price.
Inside map(), you can read each field and show it however you like.
The data lives in books.ts, apart from the component. App does not know how many books there are. It shows whatever is in the array.
Filtering Before You Show
You can change the array before you show it. For example, filter() makes a new array with only the items that match a condition.
Tick the box. "Wings of Fire" disappears, because it is not in stock. Look at this line:
const shown = onlyInStock ? books.filter((book) => book.inStock) : books;
It means: if the box is ticked, keep only the books in stock. If not, use all books.
An Empty List
When the array is empty, map() gives back an empty array, so nothing is shown. It is kind to tell the user why:
{books.length === 0 ? <p>No books found.</p> : <ul>{books.map(...)}</ul>}
What Are Keys?
A key is a special prop that you give to each item in a list. It is a short label that is unique in that list. No two items in the same list can have the same key.
<li key={book.id}>{book.title}</li>
React uses the key to tell the items apart. The key is not shown on the screen.
Animation: when a book is removed, React matches the remaining items by key, so it only removes the item with key 2 BeforeAfter removing Wings of Fire The Alchemistkey=1Wings of Firekey=2Atomic Habitskey=3 The Alchemistkey=1Atomic Habitskey=3key 1 and key 3 are kept, key 2 is removed
React uses each key to match items between renders, so it changes only what really changed.
Good keys:
- An id from your data, such as
book.id. This is the best choice. - A unique text value, such as a book title, if no two books share the same title.
Put the key on the outer element that map() returns, not on an element inside it.
Importance of Keys
When a list changes, React compares the old list with the new list. Keys tell React which item is which.
- With good keys, React knows "the item with id 3 moved to the top". It moves that item and keeps everything inside it.
- Without good keys, React matches items by their position. If you add an item at the top, React may mix up the items.
If you forget the key, React shows a warning in the console: Each child in a list should have a unique "key" prop.
Why Not Use the Index?
map() also gives you each item's position, called the index (0, 1, 2...). It is tempting to use it as the key, but it causes bugs when items are added, removed or moved. The positions change, so the keys move to different items.
Animation: after adding a book at the top, index keys move the typed note to the wrong book, while id keys keep it with the right book key = indexkey = book.id The Alchemist0Great!Wings of Fire1The Alchemistid 1Great!Wings of Fireid 2Step 1: type a note in the first row Atomic Habits0Great!The Alchemist1Wings of Fire2Atomic Habitsid 3The Alchemistid 1Great!Wings of Fireid 2✗ the note moved to the wrong book✓ the note stays with its bookStep 2: Add to top
With index keys, the new top item takes key 0 and gets the old item's note. With id keys, each note stays with its own book.
The lab below shows the problem. Each row has an input box. Type a note in the first row of both lists, then press Add to top.
In the left list, your note is now next to the new book. It stayed in the first position, because its key was the position 0. In the right list, your note is still next to "The Alchemist", because its key is the book's id.
Use a stable id from your data as the key. Use the index only when the list never changes order and items are never added or removed.
Nested Lists
A nested list is a list inside another list. For example, a shop has categories, and each category has its own books.
To show it, use map() inside another map(). Each list needs its own keys.
The outer map() makes one <section> for each category. Inside it, the inner map() makes one <li> for each book in that category.
Keys only need to be unique among siblings. So the books in different categories could share a key. But using unique ids everywhere is simplest.
Making It Easier to Read
When nested lists get long, move the inner part into its own component:
function CategorySection({ category }: { category: Category }) {
return (
<section>
<h3>{category.name}</h3>
<ul>
{category.books.map((book) => <li key={book.id}>{book.title}</li>)}
</ul>
</section>
);
}
// In App:
{categories.map((category) => <CategorySection key={category.id} category={category} />)}
The key goes on <CategorySection /> in App, because that is the element map() returns.
Common mistakes
| Mistake | What you see | Fix |
|---|---|---|
Forgetting the key | Console warning: Each child in a list should have a unique "key" prop. | Add key={item.id} to the outer element |
| Using the index as the key in a list that changes | Inputs and other content end up next to the wrong item | Use a stable id: key={book.id} |
| Two items with the same key | Console warning about duplicate keys, and items may disappear | Make every key unique in the list |
| Putting the key on an inner element | The warning still shows | Put key on the element that map() returns |
Using { } in an arrow function without return | The list is empty | Write (book) => (<li>...</li>) or add return |
Using forEach instead of map | Nothing shows | forEach returns nothing. Use map |
Changing the array with push before showing | The screen does not update | Make a new array, as in the State lesson |
Check Yourself
Exercises
What to Remember
- Keep list data in an array, and use
map()to make one element for each item. - Give every item a unique
keyon the element thatmap()returns. Use an id from your data, not the index. - For a list inside a list, use
map()inside anothermap().
Next: Form Handling