React Foundations

Lesson 1 of 8

Why React Exists

"The primary technical imperative is the management of complexity." — Steve McConnell, Code Complete

You already know JavaScript. You know how to reach into the DOM, change some text, toggle a class. So here is an uncomfortable question: if manipulating the page is that easy, why did the most demanding engineering organisation on earth invent an entire library — and later, a philosophy — just to do it? The answer is that a single DOM update is easy. Keeping ten thousand of them consistent with your data, forever, as five engineers ship features into the same screen every week, is one of the hardest problems in front-end engineering. React exists because that problem was quietly destroying products, and nobody could see it coming until they were already drowning.

The question this chapter answers

Your UI has to reflect your data — always, everywhere, no matter how the data changed. Why is keeping those two things in sync so hard by hand, and what exactly does React do so you never have to?

Core Concepts

The pre-React world, told honestly

Before React, you built a UI by mutating it. The page was already there; your job was to reach in and change the parts that needed changing. jQuery made this ergonomic and it ran the web for years: $('#cart-count').text(items.length). Grab the element, set its text. Simple, direct, and — this is the trap — manual.

The problem is that a real UI reflects the same piece of state in many places at once. Imagine a shopping cart. When a user adds an item, the cart badge in the header must update, the line-item list must grow, the subtotal must recompute, the "checkout" button must un-disable, and the empty-cart message must disappear. That's one change to your data and five places on screen that must react to it. So you write five DOM updates. Then a teammate adds a sixth spot — a "free shipping" nudge — and updates it in the add-to-cart handler but forgets the remove-from-cart handler. Now the UI lies: the cart is empty but the nudge still glows. No error is thrown. Nothing crashes. The screen is simply, silently wrong.

This is the central disease of imperative UI: state and screen drift apart. Every event handler is a little procedure that must remember to touch every affected part of the page. Miss one and you get a bug that no compiler catches. Multiply by string-template rendering (el.innerHTML = '<li>' + name + '</li>', an XSS hole waiting to happen and a re-render that blows away focus and event listeners), multiply again by a team, and you get the pre-2013 reality: front-ends that grew more fragile with every feature.

Everyday analogy

Imperative UI is editing a document by shouting corrections to a typist: "change line 3, and the total at the bottom, and the header date — oh, and the footnote." Forget one instruction and the document contradicts itself. React is handing the typist the finished document you want and letting them figure out the minimal set of edits. You stop describing changes and start describing the destination. You physically cannot forget to update the sixth place, because you never listed places at all — you described the whole page.

React's one idea: UI = f(state)

Here is the entire library in one line: your UI is a function of your state. UI = f(state). You write a function (a component) that takes the current data and returns a description of what the screen should look like for that data. You never write "when the cart changes, update the badge." You write "the badge shows items.length" — as a fact that is always true. When state changes, React calls your function again, gets a fresh description, and figures out the minimal real-DOM changes to make the screen match. The sixth place can't fall out of sync because you didn't hand-wire any of the places; you described the destination and React drives there.

This is declarative thinking — you say what, not how — and it pairs with component-based thinking: you build the UI out of small, self-contained functions that each own a slice of the screen, then compose them like LEGO. A <CartBadge>, a <LineItem>, a <Subtotal>. Each is a pure-ish function of its inputs, testable and reusable in isolation.

The machinery that makes "just re-run the whole function" affordable is the Virtual DOM. Re-touching the real DOM is expensive, and naively re-rendering everything would be slow and would wreck focus and scroll position. So React keeps a lightweight JavaScript object tree — a virtual representation of the UI. When state changes it builds a new virtual tree, diffs it against the previous one (a process called reconciliation), and applies only the differences to the real DOM. You get the mental simplicity of "redraw everything" with the performance of "change only what moved." (We'll unpack reconciliation properly in a later chapter — for now, know it's the reason declarative rendering is fast enough to be practical.)

Seeing the shift

Here is a counter written the React way. Read it, then read the prose after it.

React — Try it Yourself
Loading editor…
Preview

Look at what you did not do. You never grabbed the <p> to update its text. You never toggled the "time"/"times" wording by hand. You never wrote logic to add or remove the celebration message when the count crosses five. You stated three facts — the text shows count, the word depends on count, the message appears when count >= 5 — and React keeps all three true on every click, forever.

The imperative equivalent is a cautionary tale. You'd write document.querySelector('#count') and set its text; then a branch to pluralise "time"; then, on every click, check whether the count just crossed five and either create or remove the celebration node — remembering to remove it if the count ever drops. Three separate places to keep in sync, each a chance to forget. The React version has zero, because there are no "updates" — only a description re-evaluated. That difference, scaled to a Facebook-sized app, is the whole reason React was born.

History changed here

React was created at Facebook (now Meta) by Jordan Walke, and open-sourced at JSConf US in May 2013. It grew directly out of pain: Facebook's UI — notifications, the chat widget, the news feed — kept drifting out of sync, the classic "the badge says 3 but there are no unread messages" bug, at a scale where it was constant. An internal PHP tool called XHP had already shown that letting engineers write markup-like expressions in code reduced these bugs; React carried that idea into JavaScript as JSX. The reception was hostile — mixing markup into JavaScript was called a violation of separation of concerns, and the virtual DOM was dismissed as a needless layer. Both "controversies" won. Today the pattern React introduced — declarative, component-based UI — is how essentially the entire industry builds interfaces.

The engineer's notebook

How to actually hold React's core idea in your head:

• "I describe, React applies." Your job ends at returning the right JSX for the current state. Touching the DOM yourself is almost always a smell.
• State is the single source of truth. If the screen is wrong, the state is wrong (or the render is) — you never have to hunt for the one handler that forgot to update pixel-place-six.
• Components are functions. Same props and state in, same UI out. That predictability is what makes large React apps tractable where jQuery ones rotted.
• The Virtual DOM is an optimisation, not the point. The point is the declarative model; the VDOM is what makes it cheap enough to use.

Real-world example — chika.ng Academy

The Academy (a Next.js + React app over Drizzle/MySQL) shows a lesson page where completing a lesson has to update several things at once: the checkmark on the lesson, the "12 of 40 complete" progress bar, the percentage in the sidebar, and whether the "Get certificate" button is enabled. In a jQuery world that's four hand-wired DOM updates in the "mark complete" handler — and a fifth spot someone adds next quarter that quietly forgets to update. In React it's one fact — the progress is a function of which lessons are done — expressed once and rendered in four places from the same state. Add the certificate nudge later and it's just another expression reading the same source of truth; there is no handler to forget to update.

Common Mistakes

  • Thinking React "is the DOM." React is a description layer. When you catch yourself writing document.querySelector inside a component to change what's on screen, stop — you're fighting the model. Change state; let the render reflect it.
  • Believing the Virtual DOM is "faster than the DOM." It isn't magic speed — the real DOM is what actually renders. The VDOM's job is to compute the minimal set of real-DOM changes so you can afford to re-render declaratively. It trades a little JS work to avoid a lot of layout thrash.
  • Confusing declarative with "no logic." Declarative doesn't mean you write no conditions or loops — you saw both above. It means you express the UI as an expression of state rather than as a sequence of mutation commands.
  • Assuming React replaced JavaScript. React is JavaScript. Everything you learned in Volume 1 still applies; React is a disciplined way to organise it around state and components.
  • Reaching for React for a truly static page. A brochure page with no changing state gains little from React and pays a bundle cost. React earns its keep exactly where the UI is complex and changes — which is most apps, but not all pages.
Thought experiment

Picture a dashboard with one number — an unread-message count — shown in four places: a tab title, a header badge, a sidebar label, and a browser-notification. In the imperative world, how many lines of code touch the screen when a message arrives, and how many when one is read? (At least eight, split across two handlers — and every new place adds two more.) Now picture it in React: the count lives in one piece of state, and four expressions read it. How many screen-touching lines do you write? Zero. You change the number; React changes the four places. Now ask the real question: which of these two codebases is a new teammate more likely to break next week?

Interview Corner

Interview Corner — the same idea at three levels. Answer yours; recognise the one above it.
Junior
"What problem does React solve? Why not just use plain JavaScript and the DOM?"
Model answer — "React solves keeping the UI in sync with changing state. With plain DOM manipulation you update the screen by hand in every place your data appears, and it's easy to update five spots and forget the sixth, so the UI drifts out of sync with the data. React lets you describe what the UI should look like for a given state — UI = f(state) — and it applies the changes for you, so the screen can't fall behind the data."
Follow-up they'll throw: "So is React faster than vanilla JS?" → Not inherently — hand-tuned DOM code can be faster. React trades a little performance for correctness and maintainability at scale, and the Virtual DOM keeps the cost low.
Intermediate
"Explain declarative vs imperative UI, and where the Virtual DOM fits in."
Model answer — "Imperative UI is a sequence of mutation commands — 'find this node, change its text.' Declarative UI describes the end state — 'the badge shows the unread count' — and lets the framework compute the changes. React is declarative: you return a description (JSX) from a component, and on each state change React builds a new Virtual DOM tree, diffs it against the previous one, and applies only the differences to the real DOM. The VDOM is what makes 'just re-render everything' affordable, so you get the simplicity of declarative code without paying full re-render cost."
Follow-up: "Why not diff the real DOM directly?" → Real-DOM reads/writes are expensive and trigger layout; a plain-JS object tree is cheap to build and compare, so React does the heavy diffing in memory and touches the real DOM minimally.
Senior
"You're leading a team migrating a large jQuery app to React. Justify the move in engineering terms, not hype."
Model answer — "The jQuery app's cost isn't performance — it's that every feature adds imperative update paths, and bugs come from state and DOM drifting apart, which no test easily catches and which grows superlinearly with team size. React's win is constraining how UI updates happen: state is the single source of truth, and the UI is a pure-ish function of it, so a wrong screen means wrong state — one place to look. That predictability, plus component reuse and a typed contract via props, is what makes a large codebase survivable across many engineers. I'd migrate incrementally — mount React 'islands' inside the existing app at the highest-churn, highest-bug screens first — and measure the drop in UI-desync bugs, not raw render time."
The senior move: frame React as a complexity-management and team-scaling decision, then propose an incremental, measurable rollout rather than a big-bang rewrite.
Company lens — how the same topic gets asked
micro1Live and conversational — reason out loud. Start with the sync problem in one sentence, then UI = f(state), then the VDOM. Narrating the why beats reciting a definition.
MetaMeta created React — expect first-principles depth. Be ready to explain what problem inside Facebook forced it into existence, why JSX and the VDOM were the right calls despite the backlash, and to reason about reconciliation, not just recite "Virtual DOM good."
GoogleWants precise trade-offs. Expect "when would you not use React?" and "what does declarative cost you?" — have honest answers (bundle size, static pages, the abstraction tax).
Amazon / AWSOperational lens: how does the declarative model affect maintainability, on-call debugging, and shipping velocity across large teams? Tie React's constraints to fewer production UI bugs.
Hands-on exercise
  1. In the editor above, add a "Reset" button that sets the count back to 0. Notice you only change state — you write no code to update the paragraph, the pluralised word, or the celebration message. They all follow. That's UI = f(state) in your hands.
  2. On paper, write the imperative (vanilla-DOM) version of that same counter, including showing and hiding the "five clicks" message. Count how many separate places touch the DOM, then count how many the React version has (zero). Keep the paper — it's the argument for React in one page.
  3. Say it out loud, as in a live micro1 screen: explain in three sentences why "you update the data in five places and forget the sixth" cannot happen in idiomatic React.

Chapter Summary

  • The hard problem in UI isn't making one change — it's keeping a complex screen consistent with constantly-changing state, forever, across a team.
  • The pre-React world (manual DOM, jQuery, string templates) did this imperatively: every handler had to remember every affected spot, and forgetting one silently desynced UI from state.
  • React's core idea is UI = f(state): you describe what the UI is for the current state; React computes and applies the minimal DOM changes.
  • This makes React declarative (say what, not how) and component-based (compose small functions of their inputs).
  • The Virtual DOM diffs a new UI description against the old one (reconciliation) and touches the real DOM minimally — the optimisation that makes declarative rendering practical.
  • React was created at Meta and open-sourced in 2013 to tame Facebook's UI-sync bugs; JSX and the VDOM were controversial and won.
  • React doesn't replace JavaScript or "beat" the DOM on raw speed — it trades a little performance for correctness and maintainability at scale.
Narrative bridge

We've named React's central bargain — describe the destination, let React drive — and given it a slogan: UI = f(state). But "declarative" and "imperative" are still just words we've circled. Next chapter, Declarative vs Imperative UI, we put them side by side in code: the same feature built both ways, so you can feel in your fingers exactly what you gain, what you give up, and why the industry made this trade.

Editorial reflection — it's tempting to learn React as a bag of hooks and syntax, a thing you configure. But React is really an argument about how to fight complexity: that the way to keep a growing system correct is to remove the chances to get it wrong. UI = f(state) isn't a slogan — it's a discipline that deletes an entire category of bug by refusing to let you hand-wire the screen at all. Learn React as that idea first, and every hook you meet later will make sense as a tool in service of it.

Q&A · 0

Enrol to ask questions and join the discussion.

No questions yet — be the first to ask.