B2 · Part 1 · Beginner
Thinking in React
Turning a picture into a component tree — the step that happens before you type anything.
08On this page
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.
| Ask | If 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
- List every component that reads the value.
- Find their closest common parent.
- 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
| Mistake | Where it shows up |
|---|---|
| Storing derived values | Two sources of truth that drift apart |
| State too high | Everything re-renders; components cannot be moved |
| State too low | A sibling needs it and you cannot reach it |
| Components split by markup, not by responsibility | A "Row" that knows about filtering |
| Building interactivity before the static version | Rewriting 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."
Opens in the editor: write it, run it, and check it against real tests.
All 46 for this level →Finished reading?
0 of 57 chapters read in this series