← Back to React Course | Chapter 2: JSX & Rendering Fundamentals | Lesson 10 of 10

How Rendering Works in React

Rendering is React's way of redrawing part of a webpage whenever something it's tracking changes, like updating a scoreboard the moment the score changes.

What Triggers a Re-render

A component re-renders when its own state changes, when it receives new props from its parent, or when its parent re-renders for any reason (by default, regardless of whether that child's props actually changed).

Note: A parent re-rendering does not necessarily mean the real DOM changes -- React still diffs before touching the DOM.

Warning: Expecting a component to re-render just because some unrelated global variable changed is a common misunderstanding -- React only reacts to state/props changes it's aware of.

Example: What Triggers a Re-render

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function Child() {
  console.log('Child rendered');
  return <p>I am the child.</p>;
}
function Parent() {
  const [count, setCount] = React.useState(0);
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Parent count: {count}</button>
      <Child />
    </div>
  );
}
ReactDOM.createRoot(document.getElementById('root')).render(<Parent />);
  </script>
</body>
</html>

Render Phase vs Commit Phase

React rendering happens in two phases: the render phase calculates what should change (calling your component functions), and the commit phase actually applies those changes to the real DOM.

Note: Your component function itself should stay free of direct DOM manipulation -- that belongs in the commit phase, which React manages, or in an effect afterward.

Warning: Directly mutating the DOM inside a component's function body (during the render phase) can cause inconsistent UI, since render can run more than once before anything commits.

Example: Render Phase vs Commit Phase

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function PhaseNote() {
  const [n, setN] = React.useState(0);
  return <button onClick={() => setN(n + 1)}>Render calculates, commit applies: {n}</button>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<PhaseNote />);
  </script>
</body>
</html>

Batching Multiple State Updates

When several state updates happen inside the same event handler, React groups them into a single re-render instead of re-rendering once per update. This batching keeps the UI fast and consistent, since a component never shows a half-updated in-between state to the user.

Note: You can call multiple setState functions in a row inside one handler without worrying about extra renders -- React batches them automatically.

Warning: Because updates are batched, reading state right after calling its setter inside the same handler still gives you the OLD value, not the new one.

Example: Batching Multiple State Updates

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
    function Toggler() {
      const [a, setA] = React.useState(false);
      const [b, setB] = React.useState(false);
      function handleClick() {
        setA(true);
        setB(true);
      }
      return (
        <div>
          <button onClick={handleClick}>Set Both</button>
          <p>A: {String(a)}, B: {String(b)}</p>
        </div>
      );
    }
    ReactDOM.createRoot(document.getElementById('root')).render(<Toggler />);
  </script>
</body>
</html>
Common Mistakes
  1. Assuming every state update triggers an immediate, separate render -- React often batches multiple updates into one.
  2. Confusing the render phase (calculating what should change) with the commit phase (actually updating the DOM).
  3. Reading a state variable right after calling its setter and expecting the new value in the same function call.
Chapter Summary
  • A re-render happens when a component's state or props change.
  • React first calculates what changed (render phase) before touching the real DOM (commit phase).
  • Multiple state updates inside the same event handler are batched into a single re-render.
  • Understanding this cycle helps explain why state updates don't apply instantly mid-function.
Browser Support

No browser-specific restrictions -- an internal React rendering behavior available in every React version, with expanded automatic batching since React 18.

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.