Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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 sourceSuitable?
An id from a database or APIYes, the best option
A unique string, such as an emailYes
The array indexOnly 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.

Thanks for reading!

Donate to the site — we work hard for you.