Lists and keys
JSX has no loop of its own. To render an array, you turn it into an array of elements with map — the same method you used in the tutorial. Every element also needs a key: React uses it to tell list items apart.
A list with map
Open src/App.jsx and render an array of strings:
// src/App.jsx
export default function App() {
const todos = ['Buy milk', 'Call Oleg', 'Read a book'];
return (
<ul>
{todos.map((text) => (
<li key={text}>{text}</li>
))}
</ul>
);
}map returns an array of li elements, and JSX renders them one after another. The page shows a list of three items.
Keys
The key prop is a unique string or number for each list item. When the list changes, React uses keys to understand which item was added, removed or moved, and updates only that one. The best key is an id from the data:
// src/App.jsx
import TodoItem from './components/TodoItem.jsx';
const todos = [
{ id: 1, text: 'Buy milk', done: false },
{ id: 2, text: 'Call Oleg', done: true },
{ id: 3, text: 'Read a book', done: false },
];
export default function App() {
return (
<ul>
{todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} />
))}
</ul>
);
}The key goes on the element that map returns — here that is TodoItem, not the li inside it. The TodoItem component itself does not receive key: React keeps it for itself.
A list component
It is handy to move the list into its own component — src/components/TodoList.jsx:
// src/components/TodoList.jsx
import TodoItem from './TodoItem.jsx';
export default function TodoList({ todos }) {
return (
<ul>
{todos.map((todo) => (
<TodoItem key={todo.id} todo={todo} />
))}
</ul>
);
}App is left with one line: <TodoList todos={todos} />. The page looks the same.
Filtering before rendering
Array methods chain together. To show only unfinished tasks:
// src/components/TodoList.jsx
export default function TodoList({ todos }) {
const active = todos.filter((todo) => !todo.done);
return (
<ul>
{active.map((todo) => (
<TodoItem key={todo.id} todo={todo} />
))}
</ul>
);
}Two tasks remain: "Call Oleg" is marked as done and is not shown.
Which key to choose
| Key source | Suitable? |
|---|---|
An id from a database or API | Yes, the best option |
| A unique string, such as an email | Yes |
| The array index | Only for lists that never change |
Math.random() | No: the key is new on every render |
Common mistake
Without key the list still renders, but the browser console shows the warning "Each child in a list should have a unique key prop". Using the index as the key silences the warning, but when tasks are deleted or sorted React may mix items up — for example, a checked box stays with a different item. Use the id from the data.