Skip to the chapter
←ReactGGroundwork⚛React
React/Beginner/B2
2 / 57 written chapters
/

The cover
  1. B1Setup & JSX
  2. B2Thinking in React
  3. B3Components
  4. B4Props
  5. B5useState
  6. B6Events & conditionals
  7. B7Lists & keys
  8. B8Forms
  9. B9useEffect
  10. B10Lifting state & styling
  11. B11Guided project
  12. ★Cheat page
  1. I1useRef
  2. I2Context
  3. I3useReducer
  4. I4Custom hooks
  5. I5Effects in depth
  6. I6Routing
  7. I7State architecture
  8. I8Memoisation
  9. I9Boundaries & portals
  10. I10Data fetching
  11. I11Forms at scale
  12. I12State libraries
  13. I13Auth
  14. I14TanStack Query
  15. I15Testing
  16. I16TypeScript
  17. I17Animation
  18. I18E2E testing
  19. I19i18n
  20. I20File uploads
  21. I21Real-time UI
  22. I22shadcn/ui
  23. ★Cheat page
  1. A1Fiber
  2. A2Concurrent
  3. A3Suspense
  4. A4Server Components
  5. A5Server Actions
  6. A6use()
  7. A7Rendering strategies
  8. A8Effect timing
  9. A9External stores
  10. A10Refs in depth
  11. A11Component patterns
  12. A12Performance
  13. A13Accessibility
  14. A14Design systems
  15. A15Advanced TypeScript
  16. A16Architecture at scale
  17. A17Custom renderers
  18. A18Migrating & upgrading
  19. A19Production debugging
  20. A20Review & judgement
  21. A21State machines
  22. A22Feature flags
  23. A23Interview bank
  24. ★Cheat page

⚛B2 · Part 1 · Beginner

Thinking in React

Turning a picture into a component tree — the step that happens before you type anything.

3 min read8 sections3 exercises
2 of 57

In this chapter

  • Why this is a chapter
  • Step 1 — draw boxes on the mockup
  • Step 2 — build it static first, with no state at all
  • Step 3 — find the minimal state
  • Step 4 — put each piece where it belongs

and 3 more

about 3 min
08On this page
  1. Why this is a chapter
  2. Step 1 — draw boxes on the mockup
  3. Step 2 — build it static first, with no state at all
  4. Step 3 — find the minimal state
  5. Step 4 — put each piece where it belongs
  6. Step 5 — add the inverse data flow
  7. The mistakes this process prevents
  8. The same five steps, compressed

Why this is a chapter

Machine-coding rounds hand you a screenshot and ninety minutes. Candidates who start typing immediately spend the last twenty minutes untangling state that ended up in the wrong place. The five minutes spent here are the cheapest minutes in the round.

Step 1 — draw boxes on the mockup

Take the design and draw a box around every piece that is one thing. The test is the same one that applies to functions: if you cannot name it without saying "and", it is two boxes.

ProductPage
├── SearchBar            // input + checkbox
├── FilterPanel
│   └── CategoryChip     // repeated
└── ProductTable
    ├── CategoryRow      // repeated
    └── ProductRow       // repeated

Anything that repeats is a component — that is the easiest signal on the page. Anything with its own heading usually is too.

Step 2 — build it static first, with no state at all

Pass the data down as props and render it. No useState, no handlers, nothing interactive. It feels like a detour and it is the fastest route: you find out whether your component boundaries work before any state depends on them.

function ProductTable({ products, query }) {
  return (
    <table>
      <tbody>
        {products.map((p) => <ProductRow key={p.id} product={p} />)}
      </tbody>
    </table>
  );
}
Say this out loud in an interview

"I'll get the static version rendering from a hardcoded array first, then add state." It tells the interviewer you have done this before, and it gives you something on screen within ten minutes — which matters when the clock runs out.

Step 3 — find the minimal state

Go through every value the UI needs and ask three questions. Most values fail all three, and those are not state.

AskIf yes
Is it passed in from a parent?Props, not state
Does it stay the same over time?A constant, not state
Can you compute it from props or other state?Derive it — do not store it
products          // ✗ props — comes from the server
searchQuery       // ✓ state — the user types it
showInStockOnly   // ✓ state — the user toggles it
filteredProducts  // ✗ derived — compute it during render
resultCount       // ✗ derived — filteredProducts.length

Two pieces of state, not five. Storing filteredProducts means keeping it in sync with the query forever, and it will drift the first time somebody adds a filter.

Step 4 — put each piece where it belongs

  1. List every component that reads the value.
  2. Find their closest common parent.
  3. Put the state there. Not higher.

searchQuery is read by SearchBar, which renders it, and by ProductTable, which filters on it. Their common parent is ProductPage — so it lives there and comes down as props.

The instinct to put everything at the top "in case something needs it" is the one to resist. State at the root re-renders the whole tree and couples components to a page they should know nothing about.

Step 5 — add the inverse data flow

function ProductPage() {
  const [query, setQuery] = useState("");
  const [inStockOnly, setInStockOnly] = useState(false);

  const visible = products.filter(
    (p) => p.name.includes(query) && (!inStockOnly || p.stocked)
  );

  return (
    <>
      <SearchBar
        query={query}
        inStockOnly={inStockOnly}
        onQueryChange={setQuery}
        onStockChange={setInStockOnly}
      />
      <ProductTable products={visible} />
    </>
  );
}

The child cannot change the value; it reports that something happened and the owner decides what that means. That indirection is what makes SearchBar reusable somewhere its author never saw.

The mistakes this process prevents

MistakeWhere it shows up
Storing derived valuesTwo sources of truth that drift apart
State too highEverything re-renders; components cannot be moved
State too lowA sibling needs it and you cannot reach it
Components split by markup, not by responsibilityA "Row" that knows about filtering
Building interactivity before the static versionRewriting the tree at minute sixty

The same five steps, compressed

1. Boxes on the mockup        → the component tree
2. Static render, no state    → prove the boundaries
3. Minimal state              → three questions, most values fail them
4. Where it lives             → closest common parent, no higher
5. Callbacks down             → children report, owners decide
Interview answer, one sentence

"I break the mockup into components by responsibility, build it static from hardcoded data first so the boundaries are proven before any state depends on them, then find the minimal state by eliminating anything derivable — and put each piece at the closest common ancestor of the components that read it, not higher."

03Practice this chapter

Opens in the editor: write it, run it, and check it against real tests.

  • 10 testsProps, state, or derived?beginner
  • 11 testsDerive, don't storebeginner
  • 8 testsDerive the visible list, don't store itbeginner
All 46 for this level →
B2

Finished reading?

0 of 57 chapters read in this series

→Next stop

  1. B1Previous · B1Project setup & JSX
  2. B2you are here
  3. Next · B3Components & compositionA component is a function that takes data and returns a description of a screen.4 min read

01On this page

8 sections · 0%

  1. 01Why this is a chapter
  2. 02Step 1 — draw boxes on the mockup
  3. 03Step 2 — build it static first, with no state at all
  4. 04Step 3 — find the minimal state
  5. 05Step 4 — put each piece where it belongs
  6. 06Step 5 — add the inverse data flow
  7. 07The mistakes this process prevents
  8. 08The same five steps, compressed

[] chapters · t top