When does a component re-render in React?
Show answer — try answering out loud first
A component re-renders when its state changes, when its parent re-renders, or when a context it consumes changes. Note: "rendering" means React re-runs the component's function; it doesn't mean the DOM updates, that only happens if the result changed.
Rendering a component is, literally, running its function to get new JSX. The three causes of a re-render:
- State change: you call the
setfunction of auseState(or similar) with a different value. - Parent re-render: if the parent renders, by default all of its children do too, even if their props haven't changed. That's why changing a prop isn't an independent cause: the new props arrive because the parent re-rendered.
- Context change: if the component consumes a context with
useContextand the provider's value changes.
And the DOM? This is where reconciliation comes in:
- React runs your component and gets a lightweight description of the UI in JavaScript objects (the famous Virtual DOM).
- It compares it with the previous render's (diffing) and applies only the differences to the real DOM.
That's why re-rendering is cheap most of the time: if nothing changed in the result, React doesn't touch the DOM. Think of the Virtual DOM as a draft: it's faster to correct the draft and write only the changes to the final copy than to rewrite the whole page.
import { useState } from "react";
function Reloj({ hora }: { hora: number }) {
console.log("render de Reloj");
return <p>Segundos: {hora}</p>;
}
function Etiqueta() {
console.log("render de Etiqueta"); // also runs because of the parent
return <span>Contador de la app</span>;
}
function App() {
const [segundos, setSegundos] = useState(0);
console.log("render de App");
return (
<div>
<Etiqueta />
<Reloj hora={segundos} />
<button onClick={() => setSegundos((prev) => prev + 1)}>Avanzar</button>
</div>
);
}
// On click: console -> "render de App", "render de Etiqueta",
// "render de Reloj" (Etiqueta re-renders because its parent did).
// In the DOM only the text "Segundos: N" changes: React compared the
// result and Etiqueta's <span> stayed identical.
Mutating the state and expecting a re-render:
const [usuario, setUsuario] = useState({ nombre: "Ana" });
const renombrar = () => {
usuario.nombre = "Luis"; // BAD: mutation, the reference is THE SAME
setUsuario(usuario); // React compares with Object.is and doesn't re-render
};
// GOOD: new reference => React detects the change and re-renders
const renombrarBien = () => setUsuario((prev) => ({ ...prev, nombre: "Luis" }));
React decides to re-render by comparing the new value with the previous one. If you mutate the object, the reference doesn't change and React assumes there's nothing to do; that's why you always create a new object or array.
"A component re-renders for three reasons: its own state changed, its parent re-rendered, or a context it consumes changed. Rendering means React re-runs the component's function to get the new JSX; it doesn't imply touching the DOM. Then comes reconciliation: React compares the new description with the previous one using the Virtual DOM and applies only the differences to the real DOM. That's why a re-render is usually cheap, and I only optimize with
memooruseMemowhen I actually detect a performance problem."
Without running the code, predict what the console prints when you click the button once, and what changes in the DOM.
function Hijo() {
console.log("render Hijo");
return <p>Soy el hijo</p>;
}
function Padre() {
const [n, setN] = useState(0);
console.log("render Padre");
return (
<div>
<Hijo />
<button onClick={() => setN(n + 1)}>n = {n}</button>
</div>
);
}
See solution
// Console on click: "render Padre" and then "render Hijo".
// Padre re-renders because its state changed (n went from 0 to 1); Hijo,
// because its parent rendered, even though it receives no props.
// In the DOM only the button's text changes: "n = 0" -> "n = 1". The child's <p>
// produced the same result, so reconciliation doesn't touch that
// node: rendering is not the same as updating the DOM.