Why React & the Model
Imperative vs declarative
Section titled “Imperative vs declarative”Consider a counter. The imperative version tells the browser how to update, step by step:
// Imperative: you manage the DOM and keep it in sync by hand.let count = 0;const label = document.querySelector("#count");document.querySelector("#inc").addEventListener("click", () => { count += 1; label.textContent = count; // you must remember to do this, everywhere});The bug surface is the “remember to update” part: every place that changes count must also update every piece of UI that depends on it. Miss one and the screen lies.
The declarative version describes what the UI is for a given state, and never touches the DOM:
// Declarative: describe the UI for the current state; React syncs the DOM.function Counter() { const [count, setCount] = useState(0); return <button onClick={() => setCount(count + 1)}>{count}</button>;}There is no “update the label” step. You change count, and because the UI is described in terms of count, React re-renders and the screen is correct by construction. The class of “I forgot to update X” bugs disappears.
A component is a function of its inputs
Section titled “A component is a function of its inputs”A React component is a function that takes props (inputs from its parent) and uses state (its own memory), and returns a description of UI.
// props flow in; state lives inside; the return describes the UI.function Greeting({ name }) { // name is a prop const [count, setCount] = useState(0); // count is state return ( <div> <p>Hello, {name}</p> <button onClick={() => setCount(count + 1)}>Clicked {count} times</button> </div> );}flowchart LR props["props (from parent)"] --> comp["Component function"] state["state (own memory)"] --> comp comp --> ui["returns: UI description (elements)"] ui --> react["React renders it"]
Two rules fall out of “component is a function”:
- Props are read-only. A component must never modify its own props — they belong to the parent. Data flows down.
- Same inputs, same output. Given the same props and state, a component should render the same thing. That’s the purity requirement (a whole lesson later), and it’s what lets React re-run components freely.
Why the model matters
Section titled “Why the model matters”Everything else in React is downstream of UI = f(state):
- Hooks exist to give function components state and lifecycle without breaking the “just a function” model.
- Reconciliation exists to turn “here’s the new UI description” into “here’s the minimal DOM change.”
- Concurrent features (transitions, Suspense) exist because a pure
f(state)can be computed, paused, and restarted safely.
You are not learning a pile of APIs; you are learning one equation and its consequences.