Command Palette

Search for a command to run...

Hectal
PHASE 26Advanced ~33 min· topic 5 of 5

Topic 26.5

Machine Coding Rounds

In one line

A machine coding round asks you to build a small working UI (tabs, a star rating, nested comments, a file explorer, a stopwatch, a progress bar, pagination) in 45–90 minutes; you pass by clarifying first, planning the state shape, building a working skeleton, then adding behaviour, accessibility and polish while you talk through your choices.

Think of it like this

A cooking contest with a timer. The judges don't only taste the dish; they watch how you work. A good cook reads the recipe card twice, lays out the ingredients, gets a simple version on the plate early, and then adds garnish if there is time. A cook who starts garnishing before the rice is cooked ends up with nothing to serve. In a machine coding round the "dish" is a small working feature and the judges watch your process as much as the result.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Machine coding round
An interview where you build a small working UI feature live, usually in 45–90 minutes.
State shape
Which pieces of state you keep and how they're structured (a number, a list, a tree, a Set of ids).
Recursive component
A component that renders itself for nested data, like a comment that renders its replies as comments.
Roving tabindex
A keyboard pattern where only the active item in a group has tabIndex=0; arrow keys move focus between items.
Controlled component
A component whose value is owned by its parent and changed through an onChange prop.
Clamping
Keeping a number inside a range, such as 0–100 for a progress bar.
Skeleton (of an app)
A first rough version that renders and does the main thing, before details and styling.

Step by step

01Clarify and write the scope down

Agree the must-haves and the nice-to-haves. Put them at the top of the file so you and the interviewer can tick them off.

App.jsxwhole filejsx
/*
  Nested comments
  MUST: show tree, reply to any comment, unlimited depth
  SHOULD: collapse a thread, keyboard friendly
  NICE: edit/delete, persist in localStorage
  Data: [{ id, author, text, replies: [] }]
*/

02Plan the state and the tree

One source of truth at the top, recursion for the nesting, and a pure helper that returns a new tree.

Plan the state and the treediagram
Rendering diagram…

03Skeleton first, then behaviour

Render the static data, then add one interaction at a time and test it by hand. Commit to the simplest state that works; mention the alternatives instead of building them.

04Add the keyboard and ARIA pattern

Pick the pattern from Topic 18.4 and implement its keys. For tabs: Left/Right wrap around, Home/End jump, Tab leaves the tab list.

Add the keyboard and ARIA patterndiagram
Rendering diagram…

05Polish and walk through

Disabled states, empty states, a little CSS, then explain the code top to bottom and list what you'd do next: tests, persistence, performance for big data.

Try it yourself

  1. 1

    Add a Delete key to the tabs

    Interviewers love follow-ups. Make the tab panel show (closed) when the user presses Delete on a tab, without removing it. Where should that state live: in Tabs or in a parent? Explain your choice aloud before coding.

  2. 2

    Half stars

    Change the star rating so each star has two halves (values 0.5 to 5). Predict the change to the state shape first. (None: value stays one number; only rendering and key handling change, with steps of 0.5.)

  3. 3

    Collapse a thread

    Add a Hide replies (n) button to comments that have replies. n should count all nested replies, not just direct ones: write a small recursive countReplies(comment) and call it during render (derived, not stored).

Code & diagrams

Build 1: accessible tabs with arrow keys New tab

State is one number. `useId` makes ids unique if the component is used twice. Only the selected tab is in the Tab order (roving tabindex); the arrows wrap and focus follows the selection.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

ArrowRight: Security focused, panel: Password and 2FA
ArrowRight: Billing focused, panel: Cards and invoices
ArrowRight: Profile focused, panel: Name and photo
End: Billing focused, panel: Cards and invoices
Home: Profile focused, panel: Name and photo
Build 2: star rating (controlled, hover preview, keyboard) New tab

The parent owns `value`, so the component is controlled and reusable (a form can hold the rating). `hover` is local UI state; the shown stars are derived from `hover || value`. Each star has an accessible name, and arrow keys move both value and focus.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

click star 3: You rated 3 of 5, focus on 3 stars
ArrowRight: You rated 4 of 5, focus on 4 stars
ArrowLeft x2: You rated 2 of 5, focus on 2 stars
Build 3: nested comments with replies at any depth New tab

One tree in `Thread`, a recursive `Comment`, and a pure recursive helper that copies only the path to the changed comment. Each comment keeps its own "reply box open" state locally. For very large threads, a flat map `{ id: comment }` with `parentId` makes updates O(1) (Topic 6.1).

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

Asha: Great article!
  Ravi: Agreed.
    You: Me too
Meera: Part 2 when?
Build 4: stopwatch that doesn't drift New tab

Time is computed from timestamps, not by counting ticks: intervals drift and are slowed in background tabs. The interval only triggers repaints and is cleaned up when stopped. Laps are an append-only list, so the index key is safe here. `aria-live="off"` stops screen readers announcing every 30 ms.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

button after stop: Start
time is between 0.2 s and 1 s: true
frozen while stopped: true
after reset: 00:00.00
Build 5: progress bar driven by a fake upload New tab

`transform: scaleX` animates on the compositor (cheaper than animating `width`). The bar clamps bad values, exposes `aria-valuenow`, and the completion message is announced once through a polite live region instead of announcing every step. The effect returns the upload's cancel function as its cleanup.

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

aria-valuenow 0
aria-valuenow 25
aria-valuenow 50
aria-valuenow 75
aria-valuenow 100
Upload complete
File explorer and pagination: the state plansjsx
// File explorer: the tree is data, "open" is a Set of folder ids.
const tree = { id: "root", name: "src", children: [
  { id: "c", name: "components", children: [{ id: "b", name: "Button.jsx" }] },
  { id: "m", name: "main.jsx" },
] };
const [open, setOpen] = useState(() => new Set(["root"]));
const toggle = (id) => setOpen((prev) => {
  const next = new Set(prev);          // copy: never mutate the Set in state
  next.has(id) ? next.delete(id) : next.add(id);
  return next;
});
// A recursive <Node node={child} depth={depth + 1} /> renders folders as
// <button aria-expanded={open.has(id)}> and files as plain items.

// Pagination: the page is state, everything else is derived.
const [page, setPage] = useState(1);
const pageCount = Math.max(1, Math.ceil(items.length / pageSize));
const visible = items.slice((page - 1) * pageSize, page * pageSize);
// Prev disabled when page === 1, Next disabled when page === pageCount,
// the current page button gets aria-current="page".

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Mutate the comment tree in place

In Build 3, replace the body of onReply with comments[0].replies[0].replies.push({ id: nextId++, author: "You", text, replies: [] }); setComments(comments); and send a reply.

terminal
$ Preview
── what you'll see ──
Nothing appears. The reply is in the array, but the screen doesn't change until some other state update happens. No warning.

Break #2

Count stopwatch ticks instead of timestamps

Replace the timestamp logic with setInterval(() => setTotal((t) => t + 30), 30) and switch to another browser tab for a minute.

terminal
$ Preview
── what you'll see ──
Come back and the stopwatch shows far less than a minute: browsers slow timers in background tabs (often to once per second or less).

Myth vs fact

Myth

You should use your favourite libraries to finish faster.

Fact

Most rounds forbid UI libraries, and the point is to see how you structure state and components yourself. Ask first; plain React plus a little CSS is the safe default.

Myth

Styling is what makes a round impressive.

Fact

Working behaviour, sensible state, keyboard support and clear explanation score far more than visuals. Add CSS last.

Myth

Staying quiet and focused looks professional.

Fact

Interviewers can't score reasoning they don't hear. Narrate decisions, trade-offs and what you'd do with more time.

Myth

Recursion is too risky for a tree in an interview.

Fact

A recursive component is the clearest way to render nested data. Mention depth and performance limits and what you would change for very large trees.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    For a tree that is edited often, a normalised shape (byId map plus childIds) makes updates O(1) and avoids copying the whole path; for an interview-sized tree, the recursive copy is clearer. Say both.

  • ▸

    Make reusable widgets controlled with an optional uncontrolled mode (value/defaultValue/onChange), the same API shape as native inputs (Topic 22.2). Interviewers notice when a star rating can live inside a form library.

  • ▸

    Prefer derived state everywhere: pageCount, visible items, shown stars and nested reply counts are all computed during render. Fewer state variables means fewer contradictions to test.

  • ▸

    If you finish early, add a test: render, click with userEvent, assert with getByRole (Phase 17). Role-based queries double as an accessibility check.

Remember this

  1. 1

    Step 1, clarify (3–5 minutes). Ask about scope before typing: which features are must-have, what data shape you get (is the comments tree given, or flat with parentId?), keyboard and screen reader expectations, mobile, whether you may use libraries (usually no), and how state should behave on refresh. Write the agreed list as a comment at the top. Interviewers score this: it shows you would build the right thing at work.

  2. 2

    Step 2, plan the state shape (5 minutes). Decide the minimum state (Topic 6.1) and where it lives (Topic 6.6): for tabs, one activeIndex; for a star rating, value (owned by the parent, so the component is controlled, Topic 22.2) plus a local hover; for nested comments, one tree in the top component and a recursive child; for a file explorer, the tree plus a Set of expanded ids; for a stopwatch, startedAt and accumulated elapsed rather than a tick count (timers drift). Everything else is derived during render. Say this plan out loud and sketch the component tree.

  3. 3

    Step 3, build a working skeleton (15–20 minutes). Render static data first (Topic 2.7, thinking in React), then wire the main interaction with plain useState. Get something clickable on screen early, even ugly. Step 4, add behaviour: edge cases (empty data, the last page, clamping values, double clicks), updates that keep state immutable (Topics 4.6 and 4.7), and cleanups for timers (Topic 7.3).

  4. 4

    Step 5, accessibility. This is where strong candidates stand out. Use real elements (button, ul, form) before ARIA (Topic 18.1). Follow the known keyboard patterns (Topic 18.4): tabs use role="tablist"/tab/tabpanel, aria-selected, roving tabIndex and arrow keys; a star rating is a radiogroup of radios with aria-checked; a tree uses aria-expanded on its toggles; a progress bar uses role="progressbar" with aria-valuenow; a timer that updates every few milliseconds should not be a live region. Step 6, polish: small CSS, disabled states, focus styles, and extracting a reusable component or custom hook if time allows (Topic 10.1).

  5. 5

    Talk aloud the whole time. Say what you are about to do and why ("I'll keep the tree normalised by id so updates are O(1)… actually for this size a recursive map is clearer; I'll mention the trade-off"). When you hit a bug, narrate the debugging. Leave 5 minutes at the end to walk through the code, list what you would add next (tests with Testing Library, Phase 17; persistence; virtualisation for huge trees, Topic 24.1) and known limits. Autocomplete and infinite scroll are common prompts too: they're built step by step in Topics 24.5 and 24.2, and the design side in Topic 25.4.

  6. 6

    What interviewers score. Working core features first; sensible state (no duplicated or contradictory state); clean component boundaries and props; correct keys and immutable updates; no stale closures or leaking timers (Topic 26.3); keyboard and screen reader support; and communication. Perfect CSS is rarely on the list. A finished simple version always beats an unfinished clever one.

Explain it without notes

01

Walk through how you approach a 60-minute machine coding round, step by step.

02

How would you design the state for a file explorer with expand and collapse?

03

What makes a tabs component accessible?

04

Why build a stopwatch from timestamps instead of counting interval ticks?

Practice

01

Write a Pagination component that receives page, pageCount and onChange, renders Prev, page numbers and Next, disables Prev/Next at the ends, and marks the current page with aria-current="page".

02

Write the recursive Node component for the file explorer state plan above.

Trade-offs

  • ↔

    Building the simplest correct version first may mean a less elegant final structure, but an unfinished elegant version scores lower than a finished plain one.

  • ↔

    Recursive copies are simple for nested data; normalised maps are faster for large, frequently edited trees but take longer to write.

Done when you can

  • I follow clarify → plan state → skeleton → behaviour → accessibility → polish, and narrate as I go.

  • I can build tabs, a star rating, nested comments, a stopwatch and a progress bar from memory.

  • I can plan state for a file explorer and pagination and keep everything else derived.

  • I add the right ARIA pattern and keyboard keys for each widget.

  • I keep updates immutable and clean up every timer.

  • I know where autocomplete and infinite scroll are built (Topics 24.5 and 24.2).