Chapter 8: Rendering Lists & Keys
We’ll go through everything step by step, like I’m sitting next to you in Mumbai showing you live examples.
1. Why We Use .map() to Render Lists
In React, you cannot just write a JavaScript for loop inside JSX — because JSX expects expressions, not statements.
The cleanest and most common way to render a list is:
|
0 1 2 3 4 5 6 7 8 |
{items.map((item) => ( <SomeComponent key={somethingUnique} {...item} /> ))} |
Why .map()?
- It creates a new array of JSX elements
- React can efficiently render/update/remove DOM elements
- It’s declarative (you describe what to show, React handles how)
2. Basic Example: Simple List of Names
Create src/components/NameList.tsx
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
function NameList() { const names = ["Webliance", "Priya", "Rahul", "Sneha", "Amit"]; return ( <div style={{ padding: '40px', maxWidth: '600px', margin: '0 auto' }}> <h2 style={{ color: '#646cff' }}>My Friends List</h2> <ul style={{ listStyle: 'none', padding: 0 }}> {names.map((name) => ( <li key={name} // ← we'll talk about why this is important soon style={{ padding: '12px', margin: '8px 0', background: '#f0f4ff', borderRadius: '8px', fontSize: '18px', border: '1px solid #ddd' }} > {name} </li> ))} </ul> </div> ); } export default NameList; |
Use in App.tsx:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import NameList from './components/NameList'; function App() { return ( <div> <h1 style={{ textAlign: 'center', color: '#646cff' }}>Rendering Lists Chapter</h1> <NameList /> </div> ); } |
3. The Huge Importance of key Prop
React uses the key prop to uniquely identify each list item. Without proper keys, React cannot efficiently figure out which items changed, which were added, or which were removed.
What happens if you forget keys or use bad keys?
| Wrong key usage | Problem |
|---|---|
| No key at all | React warning in console: “Each child in a list should have a unique ‘key’ prop” |
| Use index as key (key={index}) | Major bugs when list changes (items reorder, animations break, state lost) |
| Duplicate keys | React gets confused, re-renders wrong items, performance drops |
Golden Rule (2026 best practice): Every list item must have a unique, stable key Best options (in order of preference):
- Unique ID from your data (database id, uuid) → best
- Unique natural property (username, email, product code)
- Only as last resort → index (but only if list never reorders/adds/removes in middle)
4. Dynamic Lists with Proper Unique Keys
Let’s build a realistic Todo List with add/remove functionality.
Create src/components/TodoList.tsx
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
import { useState } from 'react'; interface Todo { id: number; text: string; completed: boolean; } function TodoList() { const [todos, setTodos] = useState<Todo[]>([ { id: 1, text: 'Learn React keys', completed: false }, { id: 2, text: 'Build dynamic lists', completed: false }, { id: 3, text: 'Master conditional rendering', completed: true } ]); const [newTodo, setNewTodo] = useState(''); const addTodo = (e: React.FormEvent) => { e.preventDefault(); if (!newTodo.trim()) return; const newId = Math.max(...todos.map(t => t.id), 0) + 1; setTodos([...todos, { id: newId, text: newTodo, completed: false }]); setNewTodo(''); }; const toggleTodo = (id: number) => { setTodos(todos.map(todo => todo.id === id ? { ...todo, completed: !todo.completed } : todo )); }; const deleteTodo = (id: number) => { setTodos(todos.filter(todo => todo.id !== id)); }; return ( <div style={{ padding: '40px', maxWidth: '600px', margin: '0 auto' }}> <h2 style={{ color: '#646cff' }}>My Todo List</h2> {/* Add new todo form */} <form onSubmit={addTodo} style={{ marginBottom: '30px', display: 'flex', gap: '12px' }}> <input type="text" value={newTodo} onChange={(e) => setNewTodo(e.target.value)} placeholder="Add a new task..." style={{ flex: 1, padding: '12px', fontSize: '16px', borderRadius: '8px', border: '1px solid #ddd' }} /> <button type="submit" style={{ padding: '12px 24px', background: '#646cff', color: 'white', border: 'none', borderRadius: '8px', cursor: 'pointer' }} > Add </button> </form> {/* Todo list */} {todos.length === 0 ? ( <p style={{ textAlign: 'center', color: '#999', fontSize: '18px' }}> No tasks yet... Add your first todo! 🚀 </p> ) : ( <ul style={{ listStyle: 'none', padding: 0 }}> {todos.map((todo) => ( <li key={todo.id} // ← PERFECT: using unique id from data style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px', margin: '8px 0', background: todo.completed ? '#e0ffe0' : '#f0f4ff', borderRadius: '8px', textDecoration: todo.completed ? 'line-through' : 'none', opacity: todo.completed ? 0.7 : 1 }} > <div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}> <input type="checkbox" checked={todo.completed} onChange={() => toggleTodo(todo.id)} /> <span style={{ fontSize: '18px' }}>{todo.text}</span> </div> <button onClick={() => deleteTodo(todo.id)} style={{ background: '#ff6b6b', color: 'white', border: 'none', padding: '6px 12px', borderRadius: '6px', cursor: 'pointer' }} > Delete </button> </li> ))} </ul> )} </div> ); } export default TodoList; |
5. Why key={index} is Dangerous (Quick Demo)
If you ever use key={index} in a list that reorders or items are added/removed in the middle, React will get confused:
- Checkboxes might stay checked on wrong items
- Animations break
- Input focus jumps to wrong field
- State gets lost
Always use a stable, unique identifier from your data whenever possible.
Summary – Chapter 8 Key Takeaways
- Use .map() to turn arrays into JSX lists
- Every list item needs a unique key prop
- Best key → unique ID from your data (database id, uuid, etc.)
- Never use key={index} unless the list is static (never changes order)
- Combine with conditional rendering for empty states
- React uses keys to efficiently update the DOM
Mini Homework
- Create a ProductGrid component
- Have an array of products (at least 5) with: id, name, price, imageUrl
- Render them in a beautiful grid (use flex/grid)
- Each product card should have key={product.id}
- Bonus: Add a “Sort by price” button that re-sorts the list
