Skip to Content
React in a Week
Day 5 · Scaling up (TypeScript)

Day 5: Scaling up with TypeScript

TypeScript, context, routing, server state and error boundaries turn the Reading List into a typed, multi-page app.

Over the first four days you learned the core of React: components, props, state, effects and custom hooks. That is enough to build almost any single screen. Today is about what happens when an app grows: more files, more pages, more people touching the code, and data that lives on a server.

You will add the tools that nearly every real React codebase uses. TypeScript catches mistakes as you type. Context shares state without prop drilling. React Router gives each screen its own URL. TanStack Query handles server data and caching. Error boundaries keep one bug from blanking the whole page. None of these replace what you already know. Each one solves a problem you would hit soon if you kept building.

Time plan

LessonTimeWhat you'll do
TypeScript for React50 minType props, data, state, events and the reducer Action union
Passing data deeply with context35 minCreate, provide and read a context, and type it safely
Scaling up with reducer and context35 minBuild BooksProvider with useBooks and useBooksDispatch
Routing with React Router50 minAdd pages, a shared layout, URL parameters and redirects
Server state with TanStack Query45 minFetch and cache with useQuery, rebuild SearchSuggestions
Error boundaries35 minContain crashes with react-error-boundary and recover from them
Checkpoint50 minPut it all together in your Reading List

About 5 hours in total. Every sandbox today is TypeScript, so the files end in .ts and .tsx.

What you'll build today

By the end of the day your Reading List is a small but real app:

  • written in TypeScript, with Status, Book and a typed Action union for booksReducer;
  • with a BooksProvider that owns the reducer, so any component can read books or dispatch actions;
  • with three routes: / for the list, /books/:id for a book's detail page, and /add for the add form;
  • with search suggestions on the add page powered by TanStack Query's useQuery;
  • with an error boundary around the detail page, so a bad link shows a friendly message instead of a blank screen.

Lessons

Project checkpoint · Day 5 · Reading List

Time to upgrade your own Reading List. Work through the steps in your local project, then compare with the full code in the sandbox at the end.

Convert the project to TypeScript

The smoothest way is to start a fresh TypeScript project with Vite and move your code into it. Vite's react-ts template comes with a working tsconfig.json, so there is nothing to configure.

npm create vite@latest reading-list-ts -- --template react-ts
cd reading-list-ts
npm install

Copy your src files across and rename them: components from .jsx to .tsx, plain modules like data.js and booksReducer.js to .ts. Then create src/types.ts with Status and Book, type each component's props, and give booksReducer its Action union. VS Code will underline anything that does not fit. Running npm run build also checks every file, because the template's build script runs the TypeScript compiler first.

Move the reducer into BooksProvider

Create src/BooksContext.tsx with two contexts, a BooksProvider that calls useReducer(booksReducer, initialBooks), and the hooks useBooks and useBooksDispatch. Wrap your app in <BooksProvider> and replace every books and dispatch prop with the hooks. If you want to keep Day 4's persistence, use the initializer and effect shown in the reducer and context lesson.

Add the three routes

npm install react-router@7 @tanstack/react-query react-error-boundary

Split the screen into pages: BookListPage (the filter bar and the list), BookDetailPage, and AddBookPage (the form). Add a Layout with a header, NavLinks and an <Outlet />. In BookCard, turn the title into a <Link> to /books/ plus the book's id. After adding a book, call navigate('/').

The filter now lives inside BookListPage, so it resets when you leave the page. That is fine for today. If you prefer to keep it, store it in App.

Fetch suggestions with TanStack Query

Create one QueryClient, wrap the app in <QueryClientProvider>, and rewrite SearchSuggestions with useQuery. Use ['search', query] as the key, enabled to wait for two characters, and placeholderData: keepPreviousData. Your Day 4 effect, its loading state and its cleanup can all be deleted. Picking a suggestion fills in the add form.

Protect the detail page

Wrap the detail page in an ErrorBoundary with a FallbackComponent and resetKeys={[id]}. In the code below, the detail page throws when no book has the id from the URL, so the footer link to a missing book shows the fallback instead of a blank page. Because of resetKeys, moving to a different id clears the error automatically.

Here is the complete app for Day 5. Click a title to open its page, cycle a status to done and rate it, add a book with the help of the suggestions, and try the broken link in the footer.

Live code· Reading List, Day 5

To run this locally, the only change is the router. In App.tsx, import BrowserRouter instead of MemoryRouter and use it in the same place. Vite's dev server already sends every URL to your app, so refreshing on /books/2 works.

Tomorrow you will meet React 19's newest features: form Actions with useActionState and useOptimistic, reading promises with use(), transitions, the React Compiler, and your first tests.

Day 5 progress

0/7
Next: TypeScript for React

On this page