🎓 What You Will Learn
- Rendering Lists: Use
.map()to display arrays as UI - Keys in Lists: Why unique
keyprops matter - Adding Items: Use spread operator to add to arrays
- Removing Items: Use
.filter()to delete items - Updating Items: Modify list items with
.map() - Filtering Lists: Search and filter data dynamically
- Sorting Lists: Sort by different properties
- Nested Lists: Work with complex nested data structures
Why Lists Matter in React
Lists are everywhere in modern apps: todo items, product catalogs, user feeds, shopping carts, etc. React makes it simple to render, update, and manage lists with built-in methods like .map(), .filter(), and .sort().
Instead of manually writing HTML for each item, you describe ONE item and React repeats it for every item in your array. This is the power of component-driven development.
Rendering Lists with .map()
The .map() method transforms each item in an array into JSX. This is the primary way to render lists in React.
const items = ["Apple", "Banana", "Orange"];
// Transform each item into JSX
const listItems = items.map((item, index) => (
<li key={index}>{item}</li>
));
// Render all items
return <ul>{listItems}</ul>;
// Or inline it:
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);Keys — The Critical Prop
Every list item needs a key prop. React uses keys to track which items have changed, been added, or removed. Without keys, bugs happen.
✅ Use unique IDs from your data:
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" },
];
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li> // ✅ Use unique ID
))}
</ul>
);Adding Items to a List
To add items, use the spread operator ... to create a new array (never mutate state directly).
const [items, setItems] = useState(["Apple", "Banana"]);
const addItem = (newItem) => {
// ✅ GOOD: Create new array with spread
setItems([...items, newItem]);
// ❌ BAD: Mutating directly
// items.push(newItem); // Don't do this!
};
// Generate unique ID
const handleAdd = () => {
const newItem = {
id: Date.now(),
text: input,
completed: false
};
setItems([...items, newItem]);
};2 total • 0 completed
Removing Items from a List
Use .filter() to remove items. Filter creates a new array with only items that match your condition.
const [items, setItems] = useState([...]);
const removeItem = (idToRemove) => {
// Keep all items EXCEPT the one to remove
setItems(items.filter(item => item.id !== idToRemove));
};
return (
<>
{items.map(item => (
<div key={item.id}>
{item.name}
<button onClick={() => removeItem(item.id)}>
Delete
</button>
</div>
))}
</>
);Updating Items in a List
To update an item, use .map(). Check which item to update and return a modified version.
const [items, setItems] = useState([...]);
const updateItem = (idToUpdate, newValue) => {
setItems(
items.map(item =>
item.id === idToUpdate
? { ...item, ...newValue } // Update this item
: item // Keep others
)
);
};
// Usage
const handleUpdateQuantity = (id, newQty) => {
updateItem(id, { quantity: newQty });
};Filtering & Searching
Filter lists dynamically by storing a search term in state and using .filter().
export function ProductSearch() {
const [searchTerm, setSearchTerm] = useState("");
const products = [
{ id: 1, name: "Laptop", price: 999 },
{ id: 2, name: "Mouse", price: 29 },
{ id: 3, name: "Monitor", price: 299 },
];
// Filter products matching search
const filtered = products.filter(p =>
p.name.toLowerCase().includes(searchTerm.toLowerCase())
);
return (
<>
<input
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search..."
/>
{filtered.map(product => (
<div key={product.id}>{product.name}</div>
))}
</>
);
}Laptop
Electronics
Phone
Electronics
Notebook
Stationery
Pen
Stationery
Monitor
Electronics
Showing 5 of 5 products
Sorting Lists
Use .sort() to arrange items. Always create a copy first — [...array].sort().
const [sortBy, setSortBy] = useState("name");
const products = [
{ id: 1, name: "Laptop", price: 999 },
{ id: 2, name: "Phone", price: 599 },
];
// Create copy, then sort
const sorted = [...products].sort((a, b) => {
if (sortBy === "name") {
return a.name.localeCompare(b.name); // A-Z
} else {
return a.price - b.price; // Low to high
}
});
return (
<>
<button onClick={() => setSortBy("name")}>
Sort by Name
</button>
{sorted.map(p => (
<div key={p.id}>{p.name}</div>
))}
</>
);Nested Lists
When you have lists within lists (teams with members, categories with products), use nested .map() calls.
const teams = [
{ id: 1, name: "Frontend", members: ["Alice", "Bob"] },
{ id: 2, name: "Backend", members: ["Charlie"] },
];
return (
<>
{teams.map(team => (
<div key={team.id}>
<h3>{team.name}</h3>
<ul>
{team.members.map((member, idx) => (
<li key={idx}>{member}</li>
))}
</ul>
</div>
))}
</>
);👥 Frontend
- Alice
- Bob
👥 Backend
- Charlie
- Diana
- Eve
👥 DevOps
- Frank
Array Methods Cheat Sheet
| Method | What It Does | Example | Use For |
|---|---|---|---|
| <Code>.map()</Code> | Transform each item | items.map(x => ...) | Render lists |
| <Code>.filter()</Code> | Keep matching items | items.filter(x => ...) | Search, delete |
| <Code>.find()</Code> | Get first match | items.find(x => ...) | Find one item |
| <Code>.sort()</Code> | Order items | [...items].sort(...) | Sorting |
| <Code>.slice()</Code> | Get portion | items.slice(0, 5) | Pagination |
| <Code>.includes()</Code> | Check existence | items.includes(x) | Validation |
Best Practices
[...array].sort()Common Mistakes
// ❌ BAD: Using index as key
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
// ✅ GOOD: Using unique ID
{items.map((item) => (
<li key={item.id}>{item.name}</li>
))}// ❌ BAD: Mutating directly
items.push(newItem);
setItems(items);
// ✅ GOOD: Create new array
setItems([...items, newItem]);// ❌ BAD: Original array gets sorted
items.sort((a, b) => a - b);
setItems(items);
// ✅ GOOD: Copy first, then sort
setItems([...items].sort((a, b) => a - b));Real-World Example: Shopping Cart
import { useState } from 'react';
export function ShoppingCart() {
const [items, setItems] = useState([
{ id: 1, name: "Laptop", price: 999, quantity: 1 },
{ id: 2, name: "Phone", price: 599, quantity: 2 },
]);
const updateQuantity = (id, qty) => {
setItems(items.map(item =>
item.id === id ? { ...item, quantity: qty } : item
));
};
const removeItem = (id) => {
setItems(items.filter(item => item.id !== id));
};
const total = items.reduce(
(sum, item) => sum + (item.price * item.quantity),
0
);
return (
<>
{items.map(item => (
<div key={item.id}>
<h3>{item.name}</h3>
<p>${item.price}</p>
<input
type="number"
value={item.quantity}
onChange={(e) => updateQuantity(item.id, +e.target.value)}
/>
<button onClick={() => removeItem(item.id)}>
Remove
</button>
</div>
))}
<p>Total: ${total}</p>
</>
);
}What's Next?
- React Hooks: useEffect for fetching list data from APIs
- Performance: React.memo for list items, virtualization for large lists
- Advanced Patterns: Extract list items to separate components
- State Management: Redux or Context for complex list state
- Forms & Lists: Building dynamic forms with repeating fields
Keep practicing! 💪 Lists are fundamental in React. Build more projects with different list types (todos, products, users, etc.) and you'll master this skill quickly!