Lesson 1.7

Understanding Rendering

At its core, React is a library for building UIs from a deceptively simple idea: your view is a pure function of your state. Yet one part of that idea confuses even experienced developers: when does React actually render?

What you'll learn
  • What “rendering” really means in React
  • Exactly when React renders and re-renders components
  • How snapshots of props, state, and handlers work
  • When React skips a re-render
  • How batched state updates are calculated
  • Why children re-render and how memoization helps

You can condense React's mental model into a single equation:

text
v = f(s)

Your UI (v) is the result of calling a function (f) with your component state (s). But that raises an important question: when exactly does React call f?

What Rendering Actually Means

Rendering is the process where React calls your component function to produce a description of the UI.

  • React takes a snapshot of your component at a point in time
  • That snapshot includes props, state, event handlers, and JSX
  • React uses the JSX output to update the actual DOM
jsx
import { createRoot } from "react-dom/client"
import Dashboard from "./Dashboard"

const el = document.getElementById("root")
const root = createRoot(el)

root.render(<Dashboard />)

When Does React Re-render?

React only re-renders a component when its state changes.

If a parent component's state changes, React re-renders the parent — and then, by default, all of its children.

jsx
function Spark() {
  console.log("Spark rendered")
  return <span></span>
}

export default function Header() {
  const [count, setCount] = React.useState(0)

  return (
    <h1>
      Greetings <Spark />{" "}
      <button onClick={() => setCount(c => c + 1)}>Update</button>
    </h1>
  )
}

Snapshots and Event Handlers

When an event handler runs, it sees the props and state from the snapshot of the render in which it was created.

jsx
export default function Lamp() {
  const [mode, setMode] = React.useState("off")

  function toggle() {
    setMode("on")
    console.log("Current mode inside handler:", mode)
  }

  return <button onClick={toggle}>{mode}</button>
}

On the first click, the snapshot says mode = "off", so the console logs "off" even though you call setMode("on"). On the next render, the snapshot is updated.

When React Skips a Re-render

If you update state to the exact same value as before, React skips the re-render for that component.

jsx
export default function Counter() {
  const [n, setN] = React.useState(5)

  function reset() {
    setN(5) // same as existing state
  }

  return <button onClick={reset}>{n}</button>
}

How React Batches State Updates

Inside a single event handler, React batches state updates and applies them together after the handler finishes.

javascript
function handle() {
  setLevel(10)
  setLevel(20)
  setLevel(30)
}

The final value will be 30, not 10 → 20 → 30. With functional updates, each update can see the latest intermediate value:

javascript
function handle() {
  setLevel(1)            // Intermediate: 1
  setLevel(l => l + 4)   // Intermediate: 5
  setLevel(100)          // Overwrites: 100
  setLevel(l => l + 6)   // Final: 106
}

StrictMode and Double Rendering

In development, React's StrictMode intentionally renders components twice to help surface impure logic and unsafe side effects.

jsx
import { StrictMode } from "react"

root.render(
  <StrictMode>
    <Dashboard />
  </StrictMode>
)

This behavior happens only in development and disappears in production builds.

Summary

  • React re-renders when state changes
  • Event handlers always see the snapshot from the render in which they were defined
  • React batches state updates and applies them together
  • Parents re-render → children re-render, unless you use memoization
  • StrictMode double-renders only in development

With this mental model, most React rendering questions become predictable — even in large applications.