Rendering is React calling your component function and figuring out what the JSX describes for the current props and state โ it does not necessarily mean anything actually changes on screen. A re-render happens whenever a component's state or props update, triggering React to call the function again and compare the new output against the previous one.
function Greeting({ name }) {
console.log("Greeting rendered"); // logs every time this runs, render or re-render
return <h2>Hello, {name}</h2>;
}
// Directly manipulating the real DOM for every small change is SLOW.
// React instead:
// 1. Renders a lightweight JS object tree (the Virtual DOM) describing the UI
// 2. Compares ("diffs") the new tree against the previous one - this process is called RECONCILIATION
// 3. Calculates the minimal set of real DOM changes needed
// 4. Applies ONLY those specific changes to the actual browser DOMReal DOM operations are comparatively expensive. By batching and minimizing actual DOM changes through this diffing process, React keeps UI updates fast even in large, complex applications.
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>+</button>
<Child />
</>
);
}
function Child() {
console.log("Child rendered"); // this logs EVERY time Parent re-renders, even though Child has no relation to count!
return <p>I'm a child component</p>;
}By default, when a component re-renders, every child component nested inside it re-renders too โ regardless of whether that child actually depends on what changed. This is completely normal React behavior, but it's the exact problem Chapter 31's optimization tools solve when it becomes a real performance issue.
Returning to Chapter 10's key prop with this deeper context: React uses keys during reconciliation to match array items between renders. A stable key tells React "this is the same logical item, just possibly in a new position" โ letting React update it in place rather than destroying and recreating the DOM element (which would, for example, lose focus on an input mid-edit).
A component re-rendering (its function being called again) is not the same as the DOM actually being updated. If the newly rendered output is identical to before, React's reconciliation process detects this and skips touching the real DOM entirely โ re-rendering is comparatively cheap in React specifically because of this diffing step, so it's rarely worth panicking about a component 're-rendering too much' without first measuring (Chapter 31 covers profiling tools).
Add a console.log inside both a parent and a child component, click a button that updates the parent's state, and observe in the console which components actually re-render.
import { useState } from "react";
function Child() {
console.log("Child rendered");
return <p>Child component</p>;
}
function Parent() {
const [count, setCount] = useState(0);
console.log("Parent rendered");
return (
<>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
<Child />
</>
);
}
Q Does React re-render the entire page every time state changes?
No โ only the component where state changed, plus (by default) its child components, re-render. React never re-runs unrelated, unconnected components elsewhere in the tree just because some other state changed.
Q What's the difference between the Virtual DOM and the real DOM?
The real DOM is the browser's actual representation of the page. The Virtual DOM is a lightweight JavaScript object tree React uses internally to calculate the minimal real DOM changes needed, before touching the actual browser DOM at all.