Topic 0.2
The React Mental Model
In one line
A React app is a tree of components; each one turns data into a description of the screen, state changes make React re-render, and React then updates only the parts of the real page that changed.
Think of it like this
LEGO. A castle is built from small bricks, the bricks make walls and towers, and the towers make the castle. A React app is built the same way from components: a Button and a SearchBox make a Header, the Header and a ProductList make a ShopPage. Each piece can be built, tested and reused on its own.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Component
- A function that returns a piece of UI. Written with a capital letter and used like a tag:
<Header />. - Component tree
- How components sit inside each other: the app at the top, smaller parts below.
- Props
- The inputs a parent passes to a child component, like attributes on a tag:
<Battery level={90} />. - State
- A component's own memory that can change. Changing it makes React render the component again.
- Render
- React calling your component function to get a fresh description of the screen.
- React element
- A small plain object describing one thing to show, like
{ type: 'h1', props: { children: 'Hi' } }. - Virtual DOM
- A nickname for the tree of React elements: a lightweight description of the page kept in memory.
- Reconciliation
- React comparing the new description with the old one to find what changed.
- Commit
- React applying the changes it found to the real DOM.
Step by step
01Split the screen into components
Look at any app and draw boxes around parts that have one job. A to-do app might be: App (everything), Header (the title), TodoList (the list) and TodoItem (one row). These boxes become components.
02Data flows down as props
App owns the list of to-dos. It passes the list to TodoList as a prop, and TodoList passes one item to each TodoItem. Every component gets exactly the data it needs from its parent.
function App() {
const todos = ["Learn JSX", "Learn props", "Learn state"];
return (
<>
<Header title="My to-dos" />
<TodoList items={todos} />
</>
);
}03A state change triggers a render
When state changes, React calls that component again, plus its children. Each call returns new React elements. In the live example below, every render logs a line so you can watch it happen.
04React compares, then commits the difference
React walks the new elements and the old ones side by side. Where they match, the existing DOM node is kept. Where something differs (a text, an attribute, a new item), React changes just that. Your input fields keep their typing, your scroll position stays, and focus isn't lost.
Try it yourself
- 1
Predict the logs
In "Watch the tree render", predict exactly which three lines appear when you click once. Then click and compare.
Does
Headerrender again even though nothing about it changed? (Yes: a parent's render renders its children. Phase 16 shows how to skip that when it matters.) - 2
Move the state down
Move
useStateintoCounter(so Counter keeps its own count) and stop passingcountandonAddfrom App. Click now: which components log? Only the component that owns the state, and its children, render. - 3
Your typing survives
In the second example, type a word in the input and click Add one several times. The word stays, because React updated only the
<p>text.
Code & diagrams
The first render logs parent first, then children in order. Click the button and watch the console: the state lives in App, so App and its children render again.
Preview
Console
Nothing logged yet.Expected console output
App rendered
Header rendered
Counter rendered with count = 0React kept the very same <p> element and changed only its text. Type in the box and click: your typing stays, because React never rebuilt the input.
Preview
Console
Nothing logged yet.Expected console output
Same <p> element as before: true
Its text now: Count: 1Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Name a component with a small letter
Rename Header to header in both places in the first example.
Myth vs fact
Myth
The virtual DOM is what makes React fast.
Fact
Comparing element trees is extra work on top of updating the DOM. What it buys is a simple programming model: you describe the whole screen, React finds the minimal DOM changes. It's fast enough for almost any UI, not faster than perfectly hand-tuned DOM code.
Myth
A re-render means the DOM was rebuilt.
Fact
A render is just React calling your function. If the output is the same, React commits nothing to the DOM.
Myth
Children can change their parent's data.
Fact
Data flows down only. A child can ask for a change by calling a function the parent passed as a prop; the parent changes its own state.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Internally React keeps a tree of fibers, one per component instance, holding its state, props and effects. The element tree is rebuilt each render; the fiber tree persists and is updated. That's where your state actually lives between renders (Phase 24.1).
- ▸
Reconciliation uses two cheap rules instead of a general tree diff: elements of a different type are torn down and rebuilt, and children in a list are matched by key. These rules make the comparison O(n) instead of O(n³) (Topic 16.2).
- ▸
"Parent renders, children render" is the default. It's usually cheap, but it's why Phase 16 exists:
memo, moving state down and the React Compiler all reduce unnecessary renders.
Remember this
- 1
A component is a JavaScript function that returns a description of some UI. Its name starts with a capital letter (
Header, notheader) so React can tell it apart from HTML tags. You use it like a tag:<Header />. Components contain other components, which forms a component tree, much like the DOM tree in HTML. - 2
Data moves one way: from parent components down to their children, through props (short for properties, the inputs you pass to a component, like attributes on an HTML tag). A child can't reach up and change its parent's data. When a child needs to tell the parent something, the parent hands it a function to call. This one-way flow is why React apps are predictable: to know where a value came from, you look up the tree.
- 3
State is a component's own memory: data that belongs to it and changes over time, like the text in a search box. When state changes, React re-renders that component: it calls the function again to get a fresh description. Its children render again too, because their props may have changed.
- 4
Rendering produces React elements: small plain JavaScript objects that describe what should be on screen ("a
buttonwith this text"). They are cheap to create. People call this description the virtual DOM. After rendering, React compares the new elements with the previous ones (reconciliation) and then commits: it applies the smallest set of real DOM changes. - 5
So there are three steps every time something changes: trigger (state changed), render (React calls your components), commit (React updates the DOM). You'll study each step closely in Topic 4.8. For now remember: rendering is calling your function, committing is touching the page.
- 6
React itself only does components, rendering and updating. It doesn't fetch data, switch pages or style things. For those you use the browser's APIs, other libraries or a framework, each covered later in this course.
Explain it without notes
What is a component, and how does React tell a component from an HTML tag in JSX?
Describe one-way data flow. How does a child tell its parent that something happened?
What are the three steps React goes through when state changes?
What is the virtual DOM, and what is it for?
Practice
Draw (as a list) the component tree for a weather app with a search box, today's weather card and a 5-day forecast of day cards.
In the render watcher, add a Footer component that logs Footer rendered and renders <p>Made with React</p>. Place it after Counter. What is logged on first load?
Trade-offs
- ↔
Re-rendering whole subtrees keeps code simple but can waste work in very large trees; React gives you tools (Phase 16) to skip renders where measuring shows it matters.
- ↔
One-way data flow makes data easy to trace but means shared data must live in a common parent, sometimes far up the tree (Phase 6 and Phase 9 show how to manage that).
Done when you can
I can break a screen into a component tree.
I can explain props, state and one-way data flow.
I can name and explain trigger, render and commit.
I know a render doesn't mean the DOM was rebuilt.
I can explain what reconciliation is in one sentence.