Skip to Content
React in a Week
Day 4 · State & escape hatches

Day 4: Managing state and escape hatches

Decide where state lives, tame it with reducers, and step outside React with refs, Effects, data fetching and custom hooks.

Yesterday you made the Reading List interactive. You can add books, change their status and delete them. Today is about what happens when an app grows beyond one component: where should each piece of state live, how do you keep update logic readable, and how do you talk to things outside React, such as the browser, localStorage and a server?

This is the biggest day of the course, so it comes in two halves. The morning is about managing state: a method for structuring components, lifting state up, shaping it well and moving logic into a reducer. The afternoon is about escape hatches: refs, Effects, when not to use Effects, fetching data and writing your own hooks. Take breaks between the halves. Everything after today builds on these ideas.

Time plan

LessonTimeWhat you'll do
Thinking in React25 minTurn a mockup into components and find the minimal state
Sharing state25 minLift state up and build the FilterBar
Choosing the state structure30 minAvoid redundant state, and reset state with key
Extracting logic into a reducer30 minWrite booksReducer with four actions
Referencing values with refs25 minRemember values without re-rendering and focus inputs
Synchronizing with Effects35 minConnect to outside systems and clean up after yourself
You might not need an Effect30 minReplace unnecessary Effects with simpler code
Fetching data35 minLoad search suggestions without race conditions
Custom hooks30 minBuild useLocalStorage so your list survives a refresh
Project checkpoint35 minPut it all together in the Reading List

That's about 5 hours in total.

What you'll build today

By the end of the day your Reading List will:

  • filter books by status with a FilterBar (All, Want, Reading, Done), with the filtered list derived during render rather than stored;
  • manage every change through a booksReducer with the actions added, statusChanged, deleted and rated;
  • let you rate finished books from 1 to 5;
  • remember your books after a page refresh, thanks to a useLocalStorage custom hook;
  • suggest books as you type, through a SearchSuggestions component that fetches from a fake API and cleans up stale requests.

Today's lessons

Project checkpoint · Day 4 · Reading List

Time to bring today's pieces together in your reading-list project. You built each part in a lesson; now you will wire them into one App. The code below builds directly on the Day 3 checkpoint. If your own names differ a little, keep yours and follow the ideas.

1. Lift the filter and derive the list

Create src/FilterBar.js from the Sharing state lesson. In App, add const [filter, setFilter] = useState('all') and calculate the visible books during render:

App.js
const visibleBooks = filter === 'all' ? books : books.filter((b) => b.status === filter);

Don't store visibleBooks in state. It is derived from books and filter.

2. Move updates into booksReducer

Create src/booksReducer.js with the four actions from the reducer lesson. Keep your Day 3 handlers (handleAddBook, handleStatusChange, handleDelete), but replace their bodies with dispatch calls. handleStatusChange works out the next status with the same nextStatus helper and dispatches statusChanged. Remember to create the ID with crypto.randomUUID() in the handler, not in the reducer.

3. Add ratings

In BookCard, show five star buttons when a book's status is 'done'. Each one calls onRate(book.id, n), which dispatches { type: 'rated', id, rating: n }.

4. Persist with useLocalStorage

Create src/useLocalStorage.js from the custom hooks lesson. Store the books with it and keep the reducer by writing a small dispatch that applies booksReducer through the setter:

App.js
const [books, setBooks] = useLocalStorage('reading-list:books', initialBooks);

function dispatch(action) {
  setBooks((current) => booksReducer(current, action));
}

5. Add search suggestions

Create src/api.js with the fake searchBooks function and src/SearchSuggestions.js from the fetching lesson. When the user picks a suggestion, App dispatches an added action with a new ID and the status 'want'. If you want to try the real network in your local project, swap api.js for the Open Library version shown in that lesson.

The full Day 4 code

Here is the complete app. Try every feature: filter, add, change status, rate, delete, search, then refresh the preview and check that your books are still there.

Live code· Reading List, end of Day 4

If your books get into a strange state while experimenting, click Reset to sample books in the preview. In your local project, you can also open DevTools, go to Application, then Local Storage, and delete the reading-list:books entry.

Tomorrow you will convert this app to TypeScript, move the books into a context provider, add pages with React Router, and replace the hand-written fetching with TanStack Query.

Day 4 progress

0/10
Next: Thinking in React

On this page