0.1 Why React needs an engine
You write components that return some markup. So why is React thousands of lines of machinery instead of a function that just builds the DOM and stops? This lesson answers that — and the answer is the reason this whole course exists.
One thread does almost everything
In a web page, your JavaScript runs on a single main thread. That same thread also responds to clicks, processes typing, runs animations, calculates layout, and paints pixels to the screen.
The catch: it can only do one of those things at a time. While your JavaScript is running, the page can't respond to anything else. The click just waits.
The browser's main thread — one lane, one worker:
──[ run JS ]──[ handle click ]──[ layout ]──[ paint ]──▶ time
▲
└─ while this runs, NOTHING else on the page can happen
So any long stretch of JavaScript is a stretch where the page is frozen: a click feels ignored, typed characters appear late, an animation stutters. The user notices instantly.
The tension: a big update vs staying responsive
React's main job is to turn your components into DOM — figure out what changed and update the screen. Call that rendering work.
A small update is cheap. But a big update — say a state change that touches thousands of components — is a lot of work. And remember, all of it runs on that one main thread.
If React does the entire big update in one uninterruptible burst, it hogs the thread the whole time. The page freezes until React is finished:
Do it all at once (blocking):
──[ render the WHOLE big update ............................ ]──[ paint ]──▶
▲
user clicked HERE, but the click waits the whole time
Break it up and check in (cooperative):
──[ render a bit ]─[✓ handle click ]─[ render a bit ]─[ render a bit ]──▶
▲
the click gets handled almost right away
This is the tension at the heart of React's engine: finish a large amount of work, yet never make the user wait for it. Those two goals pull in opposite directions on a single thread.
React's answer: split the work and cooperate
Modern React doesn't render a big update as one unbroken block. Instead it does a small chunk of work, then pauses to ask: does the browser need the thread back right now?
If something more urgent is waiting — a click, some typing — React yields: it stops, lets the browser handle that, and resumes its rendering later from where it left off.
That ability — to stop partway through, hand control back, and pick up again — is exactly why React needs an engine rather than a single function call. A plain function runs start-to-finish and can't be paused. React's render work is built so it can be paused and resumed. Everything else in this course exists to make that possible.
Two cooperating systems (the high-level view)
To pull this off, React leans on a division of labor between two cooperating systems. The source-chapter framing puts it as an emergency room: triage nurses decide which patient is most urgent and why — that's Lanes. The shift scheduler decides when the doctors actually work and makes them take breaks so the front desk never freezes — that's the Scheduler.
Almost everything in this course hangs off that split:
- Lanes — React's priority system. It decides WHAT to render and WHY (a click is urgent; a background transition is not).
- Scheduler — a time-slicing system. It decides WHEN and HOW work runs, yielding back to the browser so the page stays responsive.
WHAT / WHY ─────────────► Lanes (which work matters most) WHEN / HOW ─────────────► Scheduler (do a slice, then let the browser breathe)
Don't worry about how either one works yet — each gets its own module later. For now, just hold the shape: Lanes pick the work, the Scheduler paces the work.
The real code
You don't need to read the bits yet. But it helps to see that "priority" isn't a vague idea in React — it's a concrete value. Each kind of update gets its own lane, and a click's lane really is ranked more urgent than a normal update's lane:
SyncLane = 0b0000000000000000000000000000001; // bit 0 — most urgent
DefaultLane = 0b0000000000000000000000000010000; // bit 4 — normal setState
That's the whole point of Lanes in one glance: an urgent update and an ordinary update are different things to React, and it can tell them apart.
Show a few more lanes (decoded in Module 3)
SyncLane = 0b0000000000000000000000000000001; // bit 0 — most urgent
InputContinuousLane = 0b0000000000000000000000000000100; // bit 2 — dragging, scrolling
DefaultLane = 0b0000000000000000000000000010000; // bit 4 — normal setState
TransitionLane1 = 0b0000000000000000000000001000000; // bit 6 — startTransition work
IdleLane = 0b0100000000000000000000000000000; // bit 29 — least urgent
OffscreenLane = 0b1000000000000000000000000000000; // bit 30 — hidden/Activity content
Why these are bits in a single number — and how React tests and merges them with bitwise math — is the subject of Module 3. Here, only the idea matters.