● LIVE   Breaking News & Analysis
Aibet2 Stack
2026-05-03
Web Development

Mastering React's Execution Order: A Step-by-Step Guide to Lifecycle Phases

A step-by-step guide to React's execution order: Render, Commit, and Effects phases, with detailed explanation of useLayoutEffect vs useEffect scheduling.

Introduction

Understanding when different parts of your React component execute is crucial for writing predictable, bug-free code. Many developers are surprised that useLayoutEffect runs before useEffect, or that useEffect fires after the browser paints. This guide breaks down React's internal lifecycle into clear, actionable steps. By the end, you'll be able to trace exactly when your component's rendering, effects, and side-effect scheduling happen — and why.

Mastering React's Execution Order: A Step-by-Step Guide to Lifecycle Phases
Source: dev.to

What You Need

  • A basic understanding of React components and hooks (useEffect, useLayoutEffect)
  • Familiarity with the concept of React's Reconciliation and Fiber (optional but helpful)
  • A development environment where you can run React code and check console logs

If you haven't already, consider reading the earlier parts of this series (Parts 1–4) to grasp the underlying Fiber architecture and scheduler — but this guide is designed to be self-contained.

Step 1: Understand the Three Phases of Every React Update

Every time React updates the UI, it goes through three distinct phases. Memorizing these is the foundation:

  1. Render Phase — React runs your component functions, compares the virtual DOM with the previous one, and figures out what changed. No DOM mutations happen here. This is where console.log('render') inside your function fires.
  2. Commit Phase — React takes the changes computed during the Render phase and applies them to the real DOM. This phase is synchronous and cannot be interrupted.
  3. Effects Phase — After the DOM is updated, React runs your side-effect functions (like useEffect and useLayoutEffect).

Key Insight: Effects are not part of rendering. They are separate tasks that happen after the DOM is already in place. This is why you can safely read DOM element properties inside an effect — the DOM reflects the current state by then.

Step 2: Recognize Where Your Code Runs in the Pipeline

Let's place common code patterns into the correct phase:

  • Inline code in the component body (e.g., console.log('render')) — runs during the Render phase, every time the component re-renders.
  • useEffect callback — runs during the Effects phase, after the browser has painted.
  • useLayoutEffect callback — runs during the Effects phase, but before the browser paints.
  • Cleanup functions returned from effects — run during the Effects phase of the next render (or on unmount).

This step is about classification. Once you know which phase a piece of code belongs to, you can predict its execution order relative to other code.

Step 3: Trace the Exact Order for useEffect vs useLayoutEffect

Many developers get the order wrong. Here's the actual sequence for a component that uses both hooks:

  1. Render phase: The component function runs (including console.log('render')).
  2. Commit phase: React applies DOM changes synchronously.
  3. Effects phase: useLayoutEffect callbacks run immediately, still in the same synchronous block (before the browser can paint).
  4. Browser paint: The browser renders the new DOM to the screen.
  5. Effects phase (continued): useEffect callbacks are scheduled as a separate macro task and run after the paint.

So the console output for the example in the introduction will be:
renderlayout effecteffect.

Why this matters: If you need to read layout information (like element size) and update the DOM before the user sees it, use useLayoutEffect. For data fetching or network calls, useEffect is usually appropriate (and avoids blocking the paint).

Step 4: Understand How React Schedules useEffect

The useEffect callback does not run immediately after the commit. Instead, React schedules it using its internal Scheduler (the same one used for concurrent features like React.lazy and Suspense).

  • After the commit phase, React pushes the useEffect callbacks into the Scheduler's queue.
  • The Scheduler runs them in a new macro task (or microtask, depending on the environment) — typically after the browser has had a chance to paint.
  • This is why the React documentation says useEffect runs "after paint."

In practice, this means that between the commit and the useEffect execution, you can observe an intermediate state in the DOM where the updates are visible but the side effects haven't run yet. This is intentional to avoid blocking the paint for non-urgent work.

Mastering React's Execution Order: A Step-by-Step Guide to Lifecycle Phases
Source: dev.to

Step 5: Predict the Execution Timeline in Complex Scenarios

Now combine multiple components, hooks, and state updates. The same phases apply recursively for each update cycle. Here's how to trace any scenario:

  1. Identify the triggering update (state change, props change, mount).
  2. Observe the Render phase — all components in the tree run their render functions. Logs here appear first.
  3. Observe the Commit phase — the DOM is updated. You won't see logs here unless you've written a custom commit observer.
  4. Observe Effects phase (layout effects first, then scheduled effects)useLayoutEffect logs appear; then, after paint, useEffect logs appear.
  5. Note cleanup functions: If a component re-renders, any old effect's cleanup runs before the new effect's callback (in the same phase order: layout cleanups run before layout effects, effect cleanups run before effects).

For example, consider a parent with a child, each with both hooks. The order will be:

  1. Parent render
  2. Child render
  3. Parent useLayoutEffect cleanup (if any) → Child useLayoutEffect cleanup → Parent useLayoutEffect → Child useLayoutEffect
  4. Browser paint
  5. Parent useEffect cleanup → Child useEffect cleanup → Parent useEffect → Child useEffect

This nested order ensures that child effects always run before parent effects (because children commit first).

Tips

  • Use useLayoutEffect sparingly. It can delay the browser's first paint if the callback does heavy work. Prefer useEffect for most side effects, and only switch to useLayoutEffect when you need to read layout synchronously before the user sees the screen.
  • Never read DOM values inside a render function. During the Render phase, the DOM is about to be updated, not yet updated. Use useLayoutEffect for those reads.
  • If you rely on the exact timing of effects (e.g., for animations or third-party libraries), test with requestAnimationFrame or setTimeout if needed. The scheduler's behavior can differ between environments (e.g., React Native vs web).
  • Remember that concurrent mode (React 18+) can pause rendering. In that case, the Render phase may be interrupted, but the Commit and Effects phases remain atomic. Your code that runs after commit will always see a consistent DOM.
  • Use the React Developer Tools profiler to visualize which hooks run when. This can help debug unexpected order issues.

By mastering these steps, you can confidently predict when any piece of code executes in a React application. Understanding the lifecycle is not just academic — it prevents subtle bugs related to DOM access, state updates, and performance.