Most apps display collections — product lists, search results, chat
messages. React renders lists using .map() and requires a key prop.
Basic list rendering
JSX
function TodoList({ todos }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text} {todo.done ? '✅' : '⬜'}
</li>
))}
</ul>
);
}Keys — Why they matter
JSX
// ❌ Bad — using array index as key
{todos.map((todo, index) => (
<TodoItem key={index} todo={todo} />
))}
// ✅ Good — using stable, unique IDs
{todos.map(todo => (
<TodoItem key={todo.id} todo={todo} />
))}Keys help React identify which items changed, were added, or removed. When keys change, React unmounts and remounts the component — which destroys local state. Use stable IDs (database IDs, UUIDs).
Filtering
JSX
function ActiveTodos({ todos }) {
const active = todos.filter(t => !t.done);
return (
<ul>
{active.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}Sorting
JSX
function SortedList({ items }) {
const sorted = [...items].sort((a, b) => a.name.localeCompare(b.name));
return (
<ul>
{sorted.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}Empty states
JSX
function TodoList({ todos }) {
if (todos.length === 0) {
return <p>No todos yet. Add one above!</p>;
}
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}Tips
- Always use stable, unique keys — database IDs are ideal.
- Never use
Math.random()for keys — they change on every render. - Never use array indices as keys if the list can reorder.
- Handle empty states — users shouldn't see a blank screen.
Next: forms.