Lists and Keys
Rendering Lists
In React, you render lists by using JavaScript's Array.map() to transform an array of data into an array of JSX elements. Each element in a list must have a unique key prop to help React identify which items changed.
Why Keys Matter
Keys help React efficiently update the DOM. Without keys, React re-renders the entire list on every change. With proper keys, React can identify exactly which item was added, removed, or moved.
// Basic list rendering
function FruitList() {
const fruits = ['Apple', 'Banana', 'Cherry', 'Date']
return (
<ul>
{fruits.map((fruit, index) => (
<li key={index}>{fruit}</li>
// index as key is OK here — static list, no reordering
))}
</ul>
)
}
// List of objects — use unique ID as key
function UserList() {
const users = [
{ id: 'u1', name: 'Alice', role: 'Admin', active: true },
{ id: 'u2', name: 'Bob', role: 'User', active: false },
{ id: 'u3', name: 'Carol', role: 'Editor', active: true },
]
return (
<table>
<thead>
<tr><th>Name</th><th>Role</th><th>Status</th></tr>
</thead>
<tbody>
{users.map(user => (
<tr key={user.id}> {/* stable unique ID */}
<td>{user.name}</td>
<td>{user.role}</td>
<td>
<span className={user.active ? 'badge-green' : 'badge-gray'}>
{user.active ? 'Active' : 'Inactive'}
</span>
</td>
</tr>
))}
</tbody>
</table>
)
}
// Nested lists
function CategoryList() {
const categories = [
{ id: 1, name: 'Fruits', items: ['Apple', 'Banana'] },
{ id: 2, name: 'Veggies', items: ['Carrot', 'Broccoli'] },
]
return (
<div>
{categories.map(cat => (
<div key={cat.id}>
<h3>{cat.name}</h3>
<ul>
{cat.items.map(item => (
<li key={`${cat.id}-${item}`}>{item}</li>
))}
</ul>
</div>
))}
</div>
)
}
import { useState } from 'react'
// Dynamic list with add, remove, reorder
function TaskManager() {
const [tasks, setTasks] = useState([
{ id: 1, text: 'Design UI', priority: 'high' },
{ id: 2, text: 'Write tests', priority: 'medium' },
{ id: 3, text: 'Deploy app', priority: 'low' },
])
const [newTask, setNewTask] = useState('')
const [filter, setFilter] = useState('all')
const addTask = () => {
if (!newTask.trim()) return
setTasks(prev => [
...prev,
{ id: Date.now(), text: newTask, priority: 'medium' }
])
setNewTask('')
}
const removeTask = (id) => {
setTasks(prev => prev.filter(t => t.id !== id))
}
const updatePriority = (id, priority) => {
setTasks(prev =>
prev.map(t => t.id === id ? { ...t, priority } : t)
)
}
const filteredTasks = filter === 'all'
? tasks
: tasks.filter(t => t.priority === filter)
return (
<div>
<div>
<input value={newTask} onChange={e => setNewTask(e.target.value)} />
<button onClick={addTask}>Add Task</button>
</div>
<div>
{['all','high','medium','low'].map(f => (
<button key={f} onClick={() => setFilter(f)}
style={{ fontWeight: filter === f ? 'bold' : 'normal' }}>
{f}
</button>
))}
</div>
<ul>
{filteredTasks.map(task => (
<li key={task.id}>
<span>{task.text}</span>
<select
value={task.priority}
onChange={e => updatePriority(task.id, e.target.value)}
>
<option value="high">High</option>
<option value="medium">Medium</option>
<option value="low">Low</option>
</select>
<button onClick={() => removeTask(task.id)}>✕</button>
</li>
))}
</ul>
<p>{filteredTasks.length} tasks</p>
</div>
)
}
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.