Back to path
BeginnerPulse · Project 2 of 12 ~4h· 5 milestones

Make it interactive with components and state

Continues from the last build: a static semantic shell with no behavior

Last rung you got Pulse looking right: a semantic, responsive shell with a header, a nav, and a metrics area, all real HTML that reads well with a screen reader and reflows on a phone.

React component decompositionTyping props with TypeScript interfacesuseState for local UI stateLifting state up to the lowest common ancestorControlled inputs (select, button toggles)Rendering lists with stable keysAvoiding derived state stored in useStateRecognizing and fixing prop drilling

What you'll build

A component-driven Pulse where MetricCard renders from typed data with stable keys, the date range and mobile nav are controlled state lifted to their lowest common ancestor, and no prop is drilled through more than two components untouched.

See how we teach, before you sign up

You don't just get code dumped on you. Every starter file and every solution is explained line-by-line, in plain English. Here's one real file from this project:

src/App.tsxtsx
import { Shell } from './components/Shell'

export default function App() {
  return <Shell />
}

Reading this file

  • import { Shell } from './components/Shell'Shell already lives in its own file from rung 1's decomposition into a header, nav, and main region.
  • export default function App()App stays the single mount point; it will not need its own state, Shell is the true common ancestor for this rung.
  • return <Shell />No props flow in yet. By the end of this rung Shell will own state that nothing here needs to know about.

The entry point. It renders Shell with nothing to configure yet, that is exactly the gap this rung closes.

That's 1 of 9 explained code blocks in this single project.

The build, milestone by milestone

  1. 1

    Give the metrics grid a typed shape

    4 guided steps

    A typed array plus a single presentational component means adding a metric is a one-line data change, not a new block of JSX, and it sets up rung 3 where this same array gets swapped for a real network response with the exact same shape.

  2. 2

    Turn the range label into a controlled dropdown

    4 guided steps

    This is the smallest possible example of lifting state up: two things need the range (the label in the header and, soon, the metrics themselves), so the state has to live in their shared parent, Shell, not inside the select itself.

  3. 3

    Wire the mobile nav open and closed

    4 guided steps

    This is the same lifting-state-up pattern as the date range, applied to a boolean instead of a string, and it forces you to keep the accessibility semantics from rung 1 intact while adding behavior.

  4. 4

    Make NavDrawer actually respond to isOpen

    4 guided steps

    A prop that a parent passes down is useless until the child actually reads it. This milestone is the other half of lifting state up: the parent owns the value, the child renders in response to it.

  5. 5

    Audit the tree for prop drilling and derived state

    4 guided steps

    Beginner React apps rot when state gets declared wherever a feature is being built rather than at its true common ancestor. Catching prop drilling and derived state now, while the tree is still four components deep, is far cheaper than untangling it once routing and forms arrive in later rungs.

What's inside when you start

4 starter files, ready to clone
5 guided milestones
5 full reference solutions
9 code blocks explained line-by-line
5 "is it working?" checks
4 interview questions it prepares you for

You'll walk away with

MetricsGrid rendering four typed Metric objects through one MetricCard component, keyed by stable id
A controlled DateRangeControl whose selected value lives in Shell's state and drives the header label with no separate label state
An interactive mobile nav where isNavOpen, aria-expanded, and aria-hidden all stay in sync from one boolean in Shell
A short written audit confirming no prop crosses more than two components and no state is derivable from other state or props

This is portfolio-grade. Build it free.

Sign up to unlock every milestone step-by-step, the code skeletons, full reference solutions, and checkable tasks, with your progress saved as you build.

Start building