Most real-world React applications need to display collections of data.
A shopping website might display a list of products. A social media application might display posts. A learning website might display courses or tutorials. An admin dashboard might display users, orders, or transactions.
Instead of manually writing JSX for every item, React allows you to generate UI from JavaScript arrays and objects.
For example, suppose you have an array of tutorial names:
const tutorials = [
"React Components",
"React Props",
"React State",
"React Events"
];
You can use JavaScript’s map() method to create a React element for every item:
function TutorialList() {
const tutorials = [
"React Components",
"React Props",
"React State",
"React Events"
];
return (
<ul>
{tutorials.map((tutorial) => (
<li key={tutorial}>
{tutorial}
</li>
))}
</ul>
);
}
export default TutorialList;
React renders each array item as a separate <li>.
This chapter explains how to render lists in React, how map() works, how to render arrays and objects, how to handle nested lists, why React keys are important, and how to filter and sort lists.
What Is List Rendering?
List rendering means creating multiple UI elements from a collection of data.
For example, you may have:
const users = [
"John",
"Sarah",
"Michael"
];
Instead of writing:
<ul>
<li>John</li>
<li>Sarah</li>
<li>Michael</li>
</ul>
you can generate the list dynamically:
<ul>
{users.map((user) => (
<li key={user}>
{user}
</li>
))}
</ul>
This becomes especially useful when the data comes from an API or changes over time.
For example, an API might return 100 products. You would not manually write 100 product components. You would store the data in an array and let React generate the UI.
The basic pattern is:
Data Array
↓
map()
↓
React Elements
↓
Rendered List
Why Is List Rendering Important?
List rendering is everywhere in modern applications.
Examples include:
- Product lists
- User lists
- Blog posts
- Comments
- Notifications
- Search results
- Navigation menus
- Course lists
- Shopping cart items
- Messages
- Tables
- Dashboard records
- Social media posts
For example, an e-commerce application could have:
const products = [
{
id: 1,
name: "Laptop",
price: 800
},
{
id: 2,
name: "Keyboard",
price: 50
},
{
id: 3,
name: "Mouse",
price: 25
}
];
React can transform this data into product cards.
This separates data from UI structure, making the application easier to maintain.
Rendering Lists with map()
The most common way to render lists in React is JavaScript’s map() method.
Consider:
const names = [
"John",
"Sarah",
"Michael"
];
You can render them like this:
function Users() {
const names = [
"John",
"Sarah",
"Michael"
];
return (
<ul>
{names.map((name) => (
<li key={name}>
{name}
</li>
))}
</ul>
);
}
export default Users;
The map() method goes through every item in the array.
Conceptually:
John → <li>John</li>
Sarah → <li>Sarah</li>
Michael → <li>Michael</li>
React then renders the resulting elements.
Understanding map()
map() is a JavaScript array method.
It creates a new array by transforming every item in the original array.
For example:
const numbers = [1, 2, 3];
const doubled = numbers.map((number) => {
return number * 2;
});
console.log(doubled);
The result is:
[2, 4, 6]
In React, the transformation produces JSX instead of numbers.
const numbers = [1, 2, 3];
const elements = numbers.map((number) => {
return <li key={number}>{number}</li>;
});
The result is an array of React elements.
You can place that array inside JSX:
<ul>
{elements}
</ul>
The Short map() Syntax
When the callback contains only one expression, you can use parentheses instead of return.
function App() {
const fruits = [
"Apple",
"Banana",
"Orange"
];
return (
<ul>
{fruits.map((fruit) => (
<li key={fruit}>
{fruit}
</li>
))}
</ul>
);
}
This is one of the most common React patterns.
Rendering Arrays of Objects
In real applications, lists usually contain objects rather than simple strings.
For example:
const products = [
{
id: 1,
name: "Laptop",
price: 800
},
{
id: 2,
name: "Keyboard",
price: 50
},
{
id: 3,
name: "Mouse",
price: 25
}
];
You can access the object’s properties inside map():
function Products() {
const products = [
{
id: 1,
name: "Laptop",
price: 800
},
{
id: 2,
name: "Keyboard",
price: 50
},
{
id: 3,
name: "Mouse",
price: 25
}
];
return (
<div>
{products.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
<p>${product.price}</p>
</article>
))}
</div>
);
}
export default Products;
Here:
product.name
gets the product name.
And:
product.price
gets the price.
The id is used as the React key.
Rendering Objects
A JavaScript object cannot normally be rendered directly as visible JSX content.
For example, this is not valid for displaying the object:
const user = {
name: "John",
age: 25
};
return <p>{user}</p>;
React cannot render a plain object as a child.
Instead, access its properties:
return (
<div>
<h2>{user.name}</h2>
<p>{user.age}</p>
</div>
);
If you need to display an object’s contents dynamically, you can use Object.entries().
function UserInfo() {
const user = {
name: "John",
age: 25,
country: "USA"
};
return (
<ul>
{Object.entries(user).map(([key, value]) => (
<li key={key}>
{key}: {value}
</li>
))}
</ul>
);
}
export default UserInfo;
This produces entries such as:
name: John
age: 25
country: USA
Object.keys()
You can also use Object.keys() when you only need the property names.
function UserInfo() {
const user = {
name: "John",
age: 25,
country: "USA"
};
return (
<ul>
{Object.keys(user).map((key) => (
<li key={key}>
{key}
</li>
))}
</ul>
);
}
export default UserInfo;
Object.values()
If you only need the values:
function UserInfo() {
const user = {
name: "John",
age: 25,
country: "USA"
};
return (
<ul>
{Object.values(user).map((value, index) => (
<li key={index}>
{value}
</li>
))}
</ul>
);
}
export default UserInfo;
However, if the object has stable property names, Object.entries() is often more useful because it gives you both the key and value.
Rendering Arrays of Numbers
Arrays do not have to contain objects.
You can render numbers as well.
function Numbers() {
const numbers = [10, 20, 30, 40];
return (
<ul>
{numbers.map((number) => (
<li key={number}>
{number}
</li>
))}
</ul>
);
}
export default Numbers;
Rendering Arrays of Strings
function Skills() {
const skills = [
"Java",
"React",
"SQL",
"Python"
];
return (
<ul>
{skills.map((skill) => (
<li key={skill}>
{skill}
</li>
))}
</ul>
);
}
export default Skills;
Rendering Arrays of JSX Elements
You can also create an array of React elements first.
function App() {
const items = [
<li key="html">HTML</li>,
<li key="css">CSS</li>,
<li key="javascript">JavaScript</li>
];
return (
<ul>
{items}
</ul>
);
}
export default App;
Although this works, it is usually more flexible to keep your data separate and generate JSX with map().
For example:
const technologies = [
"HTML",
"CSS",
"JavaScript"
];
return (
<ul>
{technologies.map((technology) => (
<li key={technology}>
{technology}
</li>
))}
</ul>
);
Rendering Nested Lists
Sometimes your data contains lists inside other lists.
For example, a website might have categories and products:
const categories = [
{
id: 1,
name: "Laptops",
products: [
"MacBook",
"Dell XPS"
]
},
{
id: 2,
name: "Phones",
products: [
"iPhone",
"Pixel"
]
}
];
You can use nested map() calls:
function Categories() {
const categories = [
{
id: 1,
name: "Laptops",
products: [
"MacBook",
"Dell XPS"
]
},
{
id: 2,
name: "Phones",
products: [
"iPhone",
"Pixel"
]
}
];
return (
<div>
{categories.map((category) => (
<section key={category.id}>
<h2>{category.name}</h2>
<ul>
{category.products.map((product) => (
<li key={product}>
{product}
</li>
))}
</ul>
</section>
))}
</div>
);
}
export default Categories;
The outer map() renders the categories.
The inner map() renders each category’s products.
Nested Lists with Objects
For more realistic data:
const categories = [
{
id: 1,
name: "Laptops",
products: [
{
id: 101,
name: "MacBook",
price: 999
},
{
id: 102,
name: "Dell XPS",
price: 899
}
]
},
{
id: 2,
name: "Phones",
products: [
{
id: 201,
name: "iPhone",
price: 799
},
{
id: 202,
name: "Pixel",
price: 699
}
]
}
];
The rendering can be:
function Store() {
const categories = [
{
id: 1,
name: "Laptops",
products: [
{
id: 101,
name: "MacBook",
price: 999
},
{
id: 102,
name: "Dell XPS",
price: 899
}
]
},
{
id: 2,
name: "Phones",
products: [
{
id: 201,
name: "iPhone",
price: 799
},
{
id: 202,
name: "Pixel",
price: 699
}
]
}
];
return (
<div>
{categories.map((category) => (
<section key={category.id}>
<h2>{category.name}</h2>
{category.products.map((product) => (
<article key={product.id}>
<h3>{product.name}</h3>
<p>${product.price}</p>
</article>
))}
</section>
))}
</div>
);
}
export default Store;
Notice that every list has its own appropriate key.
React Keys
When rendering a list, React needs a special key prop.
For example:
{products.map((product) => (
<div key={product.id}>
{product.name}
</div>
))}
The key helps React identify which item corresponds to which rendered element.
This becomes particularly important when a list changes.
Imagine the original list is:
Apple
Banana
Orange
Then a new item is added at the beginning:
Mango
Apple
Banana
Orange
React needs a reliable way to understand which items are existing items and which item is new.
Stable keys help React match the data items with their rendered elements.
Keys Are Not Passed as Normal Props
This is an important detail.
If you write:
<Product key={product.id} />
the key is used by React itself.
It is not available inside Product as:
function Product(props) {
console.log(props.key);
}
If the component needs the ID, pass it separately:
<Product
key={product.id}
id={product.id}
/>
Then:
function Product({ id }) {
return <p>{id}</p>;
}
Choosing Good Keys
A good key should be:
- Unique among the items in that list.
- Stable between renders.
- Associated with the actual data item.
The best option is usually a unique ID from your data.
For example:
const products = [
{
id: 101,
name: "Laptop"
},
{
id: 102,
name: "Keyboard"
}
];
Then:
{products.map((product) => (
<Product
key={product.id}
product={product}
/>
))}
This is an excellent use of keys.
Database IDs
If your data comes from a database, you may already have a unique identifier:
key={user.id}
or:
key={post.id}
or:
key={product.id}
These are usually preferable to generating new keys during rendering.
Stable Unique Values
If the data does not have an ID, another stable unique value may work.
For example:
const countries = [
"India",
"USA",
"Canada"
];
countries.map((country) => (
<li key={country}>
{country}
</li>
));
This works because the country names are unique in this particular list and remain stable.
However, if duplicate values are possible, you should use a better unique identifier.
Using Array Index as a Key
You may sometimes see:
items.map((item, index) => (
<div key={index}>
{item}
</div>
))
Using the array index as a key is not automatically wrong.
It can be acceptable when the list is static and items are never reordered, inserted, removed, or otherwise changed in a way that shifts positions.
For example, a fixed list of simple labels may be fine.
However, indexes can cause problems for dynamic lists.
Consider:
A
B
C
with keys:
0
1
2
If A is removed, the remaining items become:
B
C
Their indexes are now:
0
1
The keys no longer identify the same data items.
This can cause incorrect component state to be associated with list items in some situations.
Therefore, when stable IDs are available, prefer them.
Common Key Mistakes
Forgetting the Key
Incorrect:
{products.map((product) => (
<div>
{product.name}
</div>
))}
React may display a warning about missing keys.
Correct:
{products.map((product) => (
<div key={product.id}>
{product.name}
</div>
))}
Using a Random Key
Avoid:
key={Math.random()}
A random value changes between renders.
This prevents React from reliably matching an existing item with its previous rendered element.
Use a stable identifier instead.
Creating a New ID During Rendering
Avoid generating a new identifier every time the component renders.
For example:
key={crypto.randomUUID()}
inside a render loop is not an appropriate list key because a new value is generated on each render.
The key should come from stable data or be created when the data item itself is created.
Using Array Index for Dynamic Lists
Avoid:
key={index}
when the list can be reordered, inserted into, or deleted from.
Prefer:
key={item.id}
when possible.
Filtering Lists
You can combine filter() with map() to render only the items that meet a condition.
For example:
const products = [
{
id: 1,
name: "Laptop",
inStock: true
},
{
id: 2,
name: "Keyboard",
inStock: false
},
{
id: 3,
name: "Mouse",
inStock: true
}
];
To display only products that are in stock:
function Products() {
const products = [
{
id: 1,
name: "Laptop",
inStock: true
},
{
id: 2,
name: "Keyboard",
inStock: false
},
{
id: 3,
name: "Mouse",
inStock: true
}
];
return (
<div>
{products
.filter((product) => product.inStock)
.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
</article>
))}
</div>
);
}
export default Products;
The process is:
All Products
↓
filter()
↓
Products that match condition
↓
map()
↓
React UI
Filtering by Category
function ProductList({ products, category }) {
const filteredProducts = products.filter(
(product) => product.category === category
);
return (
<div>
{filteredProducts.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
<p>${product.price}</p>
</article>
))}
</div>
);
}
Filtering by Search Text
function SearchResults({ products, searchTerm }) {
const filteredProducts = products.filter((product) =>
product.name
.toLowerCase()
.includes(searchTerm.toLowerCase())
);
return (
<div>
{filteredProducts.map((product) => (
<p key={product.id}>
{product.name}
</p>
))}
</div>
);
}
This is a common pattern for search interfaces.
Sorting Lists
JavaScript’s sort() method can be used to change the order of items before rendering them.
For example:
const products = [
{
id: 1,
name: "Laptop",
price: 800
},
{
id: 2,
name: "Keyboard",
price: 50
},
{
id: 3,
name: "Monitor",
price: 300
}
];
You might want to display the cheapest products first.
Sorting by Price
A basic approach is:
const sortedProducts = [...products].sort(
(a, b) => a.price - b.price
);
Then:
function Products() {
const products = [
{
id: 1,
name: "Laptop",
price: 800
},
{
id: 2,
name: "Keyboard",
price: 50
},
{
id: 3,
name: "Monitor",
price: 300
}
];
const sortedProducts = [...products].sort(
(a, b) => a.price - b.price
);
return (
<div>
{sortedProducts.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
<p>${product.price}</p>
</article>
))}
</div>
);
}
export default Products;
The spread operator:
[...products]
creates a new array before sorting.
This is important because JavaScript’s sort() mutates the array it is called on.
If products is React state or otherwise should remain unchanged, avoid sorting it directly.
Descending Order
To display the highest-priced product first:
const sortedProducts = [...products].sort(
(a, b) => b.price - a.price
);
Sorting Strings
For alphabetical sorting, you can use localeCompare():
const sortedProducts = [...products].sort(
(a, b) => a.name.localeCompare(b.name)
);
For reverse alphabetical order:
const sortedProducts = [...products].sort(
(a, b) => b.name.localeCompare(a.name)
);
Filtering and Sorting Together
You can combine filtering and sorting.
For example:
function Products({ products }) {
const visibleProducts = products
.filter((product) => product.inStock)
.sort((a, b) => a.price - b.price);
return (
<div>
{visibleProducts.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
<p>${product.price}</p>
</article>
))}
</div>
);
}
However, remember that sort() mutates the array it receives.
A safer version is:
function Products({ products }) {
const visibleProducts = products
.filter((product) => product.inStock)
.toSorted((a, b) => a.price - b.price);
return (
<div>
{visibleProducts.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
<p>${product.price}</p>
</article>
))}
</div>
);
}
toSorted() creates a new sorted array instead of mutating the original. When targeting environments where toSorted() is unavailable, use the spread-copy approach:
const visibleProducts = [...products]
.filter((product) => product.inStock)
.sort((a, b) => a.price - b.price);
Rendering a List with a Reusable Component
As applications become larger, you can move individual list items into separate components.
For example:
function ProductCard({ product }) {
return (
<article>
<h2>{product.name}</h2>
<p>${product.price}</p>
</article>
);
}
Then:
function ProductList({ products }) {
return (
<div>
{products.map((product) => (
<ProductCard
key={product.id}
product={product}
/>
))}
</div>
);
}
This separation makes the application easier to maintain.
The list component manages the collection, while the card component manages how an individual item looks.
Rendering Lists from API Data
In real applications, list data often comes from an API.
For example, an API might return:
[
{
"id": 1,
"title": "React Components"
},
{
"id": 2,
"title": "React Props"
},
{
"id": 3,
"title": "React State"
}
]
Once the data is stored in state, you can render it with map():
function Tutorials({ tutorials }) {
return (
<div>
{tutorials.map((tutorial) => (
<article key={tutorial.id}>
<h2>{tutorial.title}</h2>
</article>
))}
</div>
);
}
This is one of the most common patterns in React development.
Handling an Empty List
Before rendering a list, it is often useful to handle the case where there are no items.
function ProductList({ products }) {
if (products.length === 0) {
return <p>No products found.</p>;
}
return (
<div>
{products.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
</article>
))}
</div>
);
}
This gives users meaningful feedback instead of displaying an empty area.
For search results, you might show:
No results found.
For a shopping cart:
Your cart is empty.
For notifications:
No new notifications.
Rendering Lists with Conditional Content
You can also use conditional rendering inside a list.
function Products({ products }) {
return (
<div>
{products.map((product) => (
<article key={product.id}>
<h2>{product.name}</h2>
{product.inStock ? (
<p>In stock</p>
) : (
<p>Out of stock</p>
)}
</article>
))}
</div>
);
}
This combines list rendering with conditional rendering.
Performance Considerations
Rendering a large list can involve many elements.
For ordinary lists, map() is usually perfectly appropriate.
For extremely large collections, however, rendering thousands of elements at once can affect performance.
Large applications may use techniques such as:
- Pagination
- Infinite scrolling
- Virtualization
- Server-side filtering
- Server-side pagination
These techniques reduce how much data needs to be displayed at one time.
The important point is that map() itself is not a problem. The amount of UI being rendered is what may become significant.
Image Placement: Rendering Lists
Place this image immediately after the “Rendering Lists with map()” section.
Create a modern 16:9 educational infographic showing:
Array of Data
↓
map()
↓
Multiple React Elements
↓
Rendered List
Use a small example such as:
["React", "JavaScript", "SQL"]
transforming into three UI cards.
Use the Web4Learners visual style: modern developer aesthetic, rounded cards, subtle gradients, clean typography, minimal text, and contemporary UI. Avoid an old-fashioned flowchart appearance.
Image Placement: React Keys
Place this image immediately after the “React Keys” section.
Create a modern 16:9 educational infographic explaining why React keys are needed.
Show a list such as:
Laptop → id: 101
Mouse → id: 102
Keyboard → id: 103
Then visually demonstrate React using the IDs to identify items when the list changes.
Include a small comparison:
Stable ID ✓
versus
Random Key ✕
Keep the design modern, clean, developer-focused, and easy for beginners to understand.
Image Placement: Filtering and Sorting
Place this image immediately before the “Filtering Lists” section.
Create a modern 16:9 educational graphic showing:
All Products
↓
filter()
↓
Matching Products
↓
sort()
↓
Ordered Products
↓
map()
↓
Rendered UI
Use product cards as the visual example. Keep text minimal and use a modern Web4Learners design with rounded cards, subtle gradients, clean typography, and a contemporary technology aesthetic.
Common List Rendering Mistakes
Forgetting key
Incorrect:
{users.map((user) => (
<li>{user.name}</li>
))}
Correct:
{users.map((user) => (
<li key={user.id}>
{user.name}
</li>
))}
Using Random Keys
Avoid:
key={Math.random()}
Keys should remain stable.
Using Index as a Key for Dynamic Lists
Avoid:
key={index}
when items can be reordered, inserted, or removed.
Prefer:
key={item.id}
when a stable ID exists.
Rendering a Plain Object Directly
Avoid:
<div>{user}</div>
Instead:
<div>{user.name}</div>
or transform the object’s entries when appropriate.
Mutating an Array with sort()
Avoid directly sorting state:
products.sort(...)
Prefer:
const sortedProducts = [...products].sort(...);
or use toSorted() where your target environment supports it.
Forgetting the Empty State
Do not assume the array always contains items.
if (products.length === 0) {
return <p>No products found.</p>;
}
Doing Too Much Inside map()
Keep list rendering readable.
If an individual item contains complicated UI or logic, extract it into a component:
<ProductCard
key={product.id}
product={product}
/>
Best Practices for Rendering Lists
Keep Data and UI Separate
Instead of manually writing every item, keep your data in an array:
const tutorials = [
{
id: 1,
title: "React Components"
},
{
id: 2,
title: "React Props"
}
];
Then render it:
{tutorials.map((tutorial) => (
<TutorialCard
key={tutorial.id}
tutorial={tutorial}
/>
))}
Use Stable Keys
Prefer stable IDs from your data.
key={product.id}
Avoid Mutating Arrays
Use immutable techniques when updating React state.
For example:
setProducts((currentProducts) => [
...currentProducts,
newProduct
]);
For sorting, make a copy first or use toSorted().
Handle Empty Data
Give the user useful feedback when the list has no items.
Filter Before Mapping
If you only need certain items:
products
.filter((product) => product.inStock)
.map((product) => (
<ProductCard
key={product.id}
product={product}
/>
))
Extract Complex List Items
When the JSX for an item becomes large, use a separate component.
This improves readability and makes individual items reusable.
Real-World Web4Learners Example
Imagine Web4Learners has a page containing React tutorials.
The data could look like:
const tutorials = [
{
id: 1,
title: "React Components",
category: "React",
level: "Beginner"
},
{
id: 2,
title: "React Props",
category: "React",
level: "Beginner"
},
{
id: 3,
title: "React State",
category: "React",
level: "Intermediate"
},
{
id: 4,
title: "React Hooks",
category: "React",
level: "Intermediate"
}
];
You could render the tutorials with:
function TutorialList() {
const tutorials = [
{
id: 1,
title: "React Components",
category: "React",
level: "Beginner"
},
{
id: 2,
title: "React Props",
category: "React",
level: "Beginner"
},
{
id: 3,
title: "React State",
category: "React",
level: "Intermediate"
},
{
id: 4,
title: "React Hooks",
category: "React",
level: "Intermediate"
}
];
return (
<div>
{tutorials.map((tutorial) => (
<article key={tutorial.id}>
<h2>{tutorial.title}</h2>
<p>{tutorial.category}</p>
<span>{tutorial.level}</span>
</article>
))}
</div>
);
}
export default TutorialList;
You could then add filtering:
const beginnerTutorials = tutorials.filter(
(tutorial) => tutorial.level === "Beginner"
);
And render them:
{beginnerTutorials.map((tutorial) => (
<article key={tutorial.id}>
<h2>{tutorial.title}</h2>
</article>
))}
You could also sort tutorials alphabetically:
const sortedTutorials = [...tutorials].sort(
(a, b) => a.title.localeCompare(b.title)
);
This demonstrates how filter(), sort(), and map() can work together to create dynamic content.
Practice Exercise
Build a React Course List.
Create an array containing at least six courses.
Each course should have:
idtitlecategorypricelevel
For example:
const courses = [
{
id: 1,
title: "React Fundamentals",
category: "React",
price: 29,
level: "Beginner"
}
];
Your application should:
- Render all courses using
map(). - Use a unique
key. - Display the course title, category, price, and level.
- Show
"No courses found"when the array is empty. - Filter courses by level.
- Sort courses by price.
- Avoid modifying the original array.
- Use a reusable
CourseCardcomponent.
Bonus Challenge
Add a search input.
When the user types:
React
only courses containing "React" in their title should be displayed.
Try combining:
filter()
↓
sort()
↓
map()
to create the final list.
Lists Cheat Sheet
| Concept | Example | Purpose |
|---|---|---|
| Render array | items.map(...) | Generate multiple elements |
| Array item | item | Current item |
| Object property | item.name | Access data |
| Key | key={item.id} | Identify list items |
| Filter | items.filter(...) | Select matching items |
| Sort | [...items].sort(...) | Order items without mutating original |
| Modern non-mutating sort | items.toSorted(...) | Create sorted copy |
| Nested list | items.map(...items.map(...)) | Render hierarchical data |
| Empty state | if (items.length === 0) | Handle no data |
| Reusable item | <Item key={item.id} /> | Separate item UI |
Basic List
{items.map((item) => (
<li key={item.id}>
{item.name}
</li>
))}
Filtered List
{items
.filter((item) => item.active)
.map((item) => (
<li key={item.id}>
{item.name}
</li>
))}
Sorted List
const sortedItems = [...items].sort(
(a, b) => a.name.localeCompare(b.name)
);
Nested List
{categories.map((category) => (
<section key={category.id}>
<h2>{category.name}</h2>
{category.products.map((product) => (
<p key={product.id}>
{product.name}
</p>
))}
</section>
))}
Key Takeaways
List rendering is one of the most important patterns in React because real applications constantly work with collections of data.
Remember these key points:
- Use
map()to transform arrays into React elements. - Arrays can contain strings, numbers, objects, or other data structures.
- Access object properties when rendering object data.
- Use nested
map()calls when working with nested data. - Give list elements stable and appropriate
keyvalues. - Prefer unique IDs from your data as keys.
- Avoid random values as keys.
- Avoid array indexes as keys for dynamic lists.
keyis a special React attribute and is not passed to components as a normal prop.- Use
filter()to display only items that match a condition. - Use
sort()carefully because it mutates the array. - Create a copy with
[...items]before sorting when you need to preserve the original array. toSorted()can be used when supported to create a sorted copy without mutating the original.- Handle empty lists explicitly.
- Extract complicated list items into reusable components.
- Keep list data separate from the presentation whenever practical.
The fundamental React list-rendering pattern is:
Array
↓
filter() optional
↓
sort() optional
↓
map()
↓
React Elements
↓
UI
Once you understand this pattern, you can build dynamic product catalogs, search results, dashboards, navigation menus, course pages, social feeds, tables, and many other React interfaces.