Setting up a React project with Vite
The mental model: how React renders (2)
Most real apps render lists of things — products, users, messages, notifications. In React, you render lists by transforming an array of data into an array of JSX elements using .map().
This is the single most-used pattern in all of React.
https://www.youtube.com/watch?v=fkl1Kn_QWCI
const fruits = ['apple', 'banana', 'cherry'];
return (
<ul>
{fruits.map((fruit) => (
<li key={fruit}>{fruit}</li>
))}
</ul>
);
Three things to notice:
.map() call is wrapped in {} — a JavaScript expression inside JSX.map() returns an array, and React renders an array of JSX elements in orderkey prop — this is required, and React will warn you if it's missingReact uses key to track which items are which across re-renders. When your list changes — items added, removed, or reordered — React uses keys to figure out the minimal set of DOM updates needed. Without keys, React has to re-render the entire list every time anything changes.
// ✅ Good — stable unique ID from your data
{users.map((user) => (
<UserCard key={user.id} {...user} />
))}
// ⚠️ Only acceptable when the list never changes order or length
{users.map((user, index) => (
<UserCard key={index} {...user} />
))}
// ❌ New key on every render — React re-mounts the component each time
{users.map((user) => (
<UserCard key={Math.random()} {...user} />
))}
Key rules:
The key goes on the outermost element returned from the .map() callback — in the examples above, that's <UserCard>, not something inside it.
<aside> ⚠️
Warning
Warning: Each child in a list should have a unique "key" prop.
You'll see this in the console when you forget a key. Find the .map() that's missing it and add key={item.id} (or whatever uniquely identifies that item) to the element you return.
</aside>
.map() is plain JavaScript, so you can chain .filter(), .sort(), and any other array method before it:
const onlineUsers = users
.filter((user) => user.isOnline)
.sort((a, b) => a.name.localeCompare(b.name));
return (
<ul>
{onlineUsers.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
Do the filtering and sorting before the return, assign the result to a variable, then map over that. Keeps your JSX readable.
<aside> ⌨️
Hands On
Given this array:
const cities = [
{ id: 1, name: 'Amsterdam', population: 921000 },
{ id: 2, name: 'Rotterdam', population: 651000 },
{ id: 3, name: 'Utrecht', population: 361000 },
{ id: 4, name: 'Den Haag', population: 548000 },
];
Render a list of city names sorted alphabetically. Then add a second list showing only cities with a population above 600,000. Make sure both lists have proper keys.
</aside>
When the array is empty, your .map() returns nothing and the screen shows a blank space. That's confusing for users. Always handle it:
return (
<div>
{users.length === 0 ? (
<p>No users yet.</p>
) : (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
)}
</div>
);
<aside> 💡
Info
For longer lists, you might also want to handle a loading state (data is being fetched) and an error state (the fetch failed). We'll get to that when we cover data fetching in week 10. The pattern is the same — just more conditions to check before you render the list.
</aside>
interface BookProps {
title: string;
author: string;
year: number;
}
function Book({ title, author, year }: BookProps) {
return (
<li>
<strong>{title}</strong> — {author} ({year})
</li>
);
}
function BookList() {
const books = [
{ id: 1, title: 'Sapiens', author: 'Yuval Noah Harari', year: 2011 },
{ id: 2, title: 'Clean Code', author: 'Robert C. Martin', year: 2008 },
{ id: 3, title: 'The Pragmatic Programmer', author: 'Hunt & Thomas', year: 1999 },
];
return (
<section>
<h2>My bookshelf ({books.length} books)</h2>
{books.length === 0 ? (
<p>No books yet.</p>
) : (
<ul>
{books.map((book) => (
<Book key={book.id} {...book} />
))}
</ul>
)}
</section>
);
}
BookList owns the data. Book receives it as props and renders it. The key sits on <Book> — the outermost element in the .map() callback. This is the pattern you'll use throughout the course.
<aside> ⌨️
Hands On
Build a ProductCard component with props title, price, description, and available (boolean). Then build a Shop component that maps over an array of at least four product objects and renders a ProductCard for each. Add an empty state message for when the array is empty.
Stretch: filter the list to only show available products. You'll need to hardcode a filtered array for now — next week you'll learn to do this dynamically with state.
</aside>
<aside> 🎉
Celebration
Lists, components, and props working together is the core loop of building UIs in React. You now have all three. Everything from here builds on this foundation.
</aside>
The HackYourFuture curriculum is licensed under CC BY-NC-SA 4.0 *https://hackyourfuture.net/*

Built with ❤️ by the HackYourFuture community · Thank you, contributors
Found a mistake or have a suggestion? Let us know in the feedback form.