Describing the UI
Day 2 turns one hard-coded component into a data-driven list, with props, children, conditions, lists, purity and styling.
Yesterday you wrote your first component. It worked, but it could only ever show one book, because the title and author were typed straight into the JSX. Today you'll fix that. By the end of the day your components will take data and turn it into UI, whatever that data happens to be.
Everything today is about the describing half of React: given some data, what should the screen look like? Nothing will respond to clicks yet. That comes on Day 3, and it will be much easier once you can describe any UI from data. That is why this day comes first.
Time plan
Plan for about four and a half hours, including breaks. Each lesson has small sandboxes to play with as you read, so the times include experimenting.
| Lesson | Time | What you'll do |
|---|---|---|
| Passing props | 40 min | Make BookCard show any book by passing a book prop |
| Passing JSX as children | 30 min | Build wrapper components like cards, panels and layouts |
| Conditional rendering | 40 min | Show a status badge and a rating only when a book has one |
| Rendering lists | 50 min | Turn an array of books into a BookList with proper keys |
| Keeping components pure | 35 min | Learn the one rule React relies on, and why Strict Mode renders twice |
| Styling components | 40 min | Style cards and badges with className, CSS files and inline styles |
| Project checkpoint | 45 min | Put it all together in your Reading List app |
What you'll build today
On Day 1 your Reading List had two hard-coded BookCards. Today it becomes data-driven:
- a
data.jsfile that exportsinitialBooks, an array of five book objects; - a
BookCardthat receives a wholebookas a prop and shows a colored status badge, plus the rating only when there is one; - a
BookListthat maps over the books and renders oneBookCardeach, withkey={book.id}; - a
styles.cssfile that turns all of that into tidy cards.
Each book has the same shape, and the rest of the course keeps it:
{ id: '1', title: 'The Hobbit', author: 'J.R.R. Tolkien', status: 'done', rating: 5 }status is always one of 'want', 'reading' or 'done'. rating is optional, so some books have it and some don't.
Lessons
Passing props
Give one component different data each time it is used.
Passing JSX as children
Nest content inside your own components and build wrappers.
Conditional rendering
Use if, ternaries, && and null to show the right thing.
Rendering lists
Turn arrays into components with map, filter and key.
Keeping components pure
Same props, same output: the rule behind React.
Styling components
className, CSS files, class names from data and inline styles.
Project checkpoint
Time to bring today's lessons into your Reading List. Try each step yourself first, then compare with the full code at the end. The sandbox uses .js file names. In your Vite project, components live in src/ and use the .jsx extension, so BookCard.js here is src/BookCard.jsx there.
Move the data into data.js
Create src/data.js and export an array called initialBooks with five books. Give each one a unique string id, a status of 'want', 'reading' or 'done', and add a rating to only some of the finished books. The name initialBooks matters: on Day 3 it becomes the starting value for your state.
Make BookCard data-driven
Change BookCard to take a single book prop instead of hard-coded text. Add a status badge whose label comes from a lookup object and whose class is badge badge- plus the status. Show the rating line only when book.rating !== undefined.
Create BookList
Create src/BookList.jsx. It receives books and returns a div with the class book-list, mapping each book to <BookCard key={book.id} book={book} />. If the array is empty, return a friendly message instead.
Update App
App keeps its <h1>My Reading List</h1> and renders <BookList books={initialBooks} /> instead of the two hand-written cards. App holds no state yet. That changes tomorrow.
Add the styles
Create src/styles.css with the classes used above and import it once at the top of src/main.jsx with import './styles.css';. You can delete the starter App.css and its import from App.jsx if you no longer need them. The sandbox loads styles.css for you automatically, which is why its App.js doesn't import it.
Here is the complete Day 2 code. Edit it freely: add a sixth book in data.js, change a status, or remove a rating and watch the card update.
When your local app matches this, you're done for the day. Tomorrow, on Day 3, the list comes alive: you'll keep the books in state, add new ones with a form, and change a book's status with a click.
Day 2 progress