Bird
Raised Fist0
Reactframework~10 mins

Effect execution timing in React - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Effect execution timing
Component Render Start
↓
Evaluate JSX
↓
Commit DOM Updates
↓
Run useEffect Cleanup (if any)
↓
Run useEffect Callback
↓
Wait for next render or unmount
This flow shows how React runs effects after rendering and DOM updates, including cleanup before running new effects.
Execution Sample
React
import React, { useState, useEffect } from 'react';

function Timer() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    const id = setInterval(() => setCount(c => c + 1), 1000);
    return () => clearInterval(id);
  }, []);
  return <div>{count}</div>;
}
This React component uses useEffect to start a timer that increments count every second, cleaning up on unmount.
Execution Table
StepTriggerState BeforeActionState AfterWhat Re-rendersDOM Change
1Initial rendercount=0Render JSX <div>0</div>count=0Timer componentDisplay 0
2Commit phasecount=0Run useEffect callback: start intervalcount=0No re-render yetNo change
3After 1 secondcount=0Interval callback: setCount(1)count=1Timer componentDisplay 1
4Render due to state changecount=1Render JSX <div>1</div>count=1Timer componentUpdate display to 1
5Commit phasecount=1No cleanup needed (first effect run)count=1No re-renderNo change
6After 2 secondscount=1Interval callback: setCount(2)count=2Timer componentDisplay 2
7Render due to state changecount=2Render JSX <div>2</div>count=2Timer componentUpdate display to 2
8Commit phasecount=2No cleanup neededcount=2No re-renderNo change
9Component unmountcount=2Run useEffect cleanup: clearIntervalcount=2Timer component removedRemove display
💡 Component unmount triggers cleanup, stopping the interval and ending updates.
Variable Tracker
VariableStartAfter 1After 2After 3Final
count0123Stopped at unmount
Key Moments - 3 Insights
Why does the effect run after the component renders and not during?
React runs effects after the DOM updates to avoid blocking rendering and to ensure the DOM is ready. See execution_table steps 2 and 5 where effects run after render and commit.
When and why does the cleanup function run?
Cleanup runs before the next effect or on unmount to avoid memory leaks. In the table, cleanup runs at step 9 when the component unmounts.
Why doesn't the effect run on every render in this example?
Because the dependency array is empty ([]), the effect runs only once after the initial render, as shown in step 2.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what is the value of count at step 4?
A0
B1
C2
DUndefined
💡 Hint
Check the 'State After' column at step 4 in the execution_table.
At which step does the useEffect cleanup function run?
AStep 9
BStep 5
CStep 2
DStep 7
💡 Hint
Look for 'Run useEffect cleanup' in the 'Action' column.
If the dependency array was omitted, how would the effect execution change?
AEffect runs only once after initial render
BEffect never runs
CEffect runs after every render
DEffect runs only on unmount
💡 Hint
Recall how useEffect behaves without dependencies; check the explanation in key_moments.
Concept Snapshot
useEffect runs after render and DOM update.
Cleanup runs before next effect or on unmount.
Empty dependency array means effect runs once.
State changes trigger re-render and possibly effect cleanup.
Effects do not block UI rendering.
Full Transcript
This visual trace shows how React's useEffect hook executes after the component renders and commits DOM updates. Initially, the component renders with count 0. Then the effect callback runs, starting an interval timer. Every second, the interval updates count, causing re-renders. Each re-render updates the displayed count. Cleanup runs only when the component unmounts, stopping the timer. The effect does not run on every render because the dependency array is empty. This ensures effects run at the right time without blocking UI updates.

Practice

(1/5)
1. In React, when does the useEffect hook run its effect function by default?
easy
A. Only when the component unmounts
B. Before the component renders
C. Only once when the component mounts
D. After every render of the component

Solution

  1. Step 1: Understand default useEffect behavior

    By default, useEffect runs after every render, including the first render and all updates.
  2. Step 2: Compare with other lifecycle timings

    It does not run before render or only once unless dependencies are specified.
  3. Final Answer:

    After every render of the component -> Option D
  4. Quick Check:

    Default effect runs after render [OK]
Hint: Default useEffect runs after every render unless dependencies given [OK]
Common Mistakes:
  • Thinking useEffect runs before render
  • Assuming it runs only once without dependencies
  • Confusing cleanup timing with effect timing
2. Which of the following is the correct syntax to run a useEffect only once when the component mounts?
easy
A. useEffect(() => { /* effect */ }, [true])
B. useEffect(() => { /* effect */ })
C. useEffect(() => { /* effect */ }, [])
D. useEffect(() => { /* effect */ }, [null])

Solution

  1. Step 1: Identify dependency array usage

    An empty array [] means the effect runs only once after the first render (mount).
  2. Step 2: Check other options

    Omitting dependencies runs every render; non-empty arrays cause effect to run on changes.
  3. Final Answer:

    useEffect(() => { /* effect */ }, []) -> Option C
  4. Quick Check:

    Empty dependency array = run once on mount [OK]
Hint: Empty array runs effect once on mount [OK]
Common Mistakes:
  • Omitting dependency array runs effect every render
  • Using non-empty arrays thinking it runs once
  • Confusing null or true as empty array
3. Consider this React component:
function Counter() {
  const [count, setCount] = React.useState(0);
  React.useEffect(() => {
    console.log('Effect:', count);
    return () => console.log('Cleanup:', count);
  }, [count]);
  return  setCount(count + 1)}>Increment;
}

What will be logged to the console after clicking the button twice?
medium
A. Effect: 0, Cleanup: 0, Effect: 1, Cleanup: 1, Effect: 2
B. Effect: 0, Effect: 1, Effect: 2
C. Effect: 0, Cleanup: 0, Cleanup: 1, Effect: 2
D. Cleanup: 0, Cleanup: 1, Effect: 2

Solution

  1. Step 1: Understand effect and cleanup with dependencies

    Effect runs after mount and after each count change. Cleanup runs before effect re-runs or unmount.
  2. Step 2: Trace logs on two clicks

    Initial mount: Effect: 0
    First click: Cleanup: 0, Effect: 1
    Second click: Cleanup: 1, Effect: 2
  3. Final Answer:

    Effect: 0, Cleanup: 0, Effect: 1, Cleanup: 1, Effect: 2 -> Option A
  4. Quick Check:

    Effect runs after render; cleanup before next effect [OK]
Hint: Cleanup runs before next effect when dependencies change [OK]
Common Mistakes:
  • Ignoring cleanup logs
  • Assuming cleanup runs after effect
  • Missing initial effect run on mount
4. What is wrong with this React effect code?
React.useEffect(() => {
  const id = setInterval(() => console.log('Tick'), 1000);
  return clearInterval(id);
}, []);
medium
A. The effect will run multiple times because dependencies are missing
B. The cleanup function should be a function, not the result of clearInterval
C. setInterval should be replaced with setTimeout
D. The effect will never run because of missing dependencies

Solution

  1. Step 1: Check cleanup function syntax

    The cleanup must be a function returning a function, but here it calls clearInterval immediately.
  2. Step 2: Correct cleanup usage

    It should return a function: return () => clearInterval(id); to run cleanup on unmount.
  3. Final Answer:

    The cleanup function should be a function, not the result of clearInterval -> Option B
  4. Quick Check:

    Cleanup must be a function returning a function [OK]
Hint: Cleanup must be a function, not a direct call [OK]
Common Mistakes:
  • Returning cleanup call instead of function
  • Confusing dependencies with cleanup
  • Thinking setInterval needs setTimeout
5. You want a React effect to run only when either propA or stateB changes, but not on every render. Which dependency array is correct?
React.useEffect(() => {
  // effect code
}, ???);
hard
A. [propA, stateB]
B. []
C. [propA || stateB]
D. [propA && stateB]

Solution

  1. Step 1: Understand dependency array purpose

    The effect runs when any value in the array changes compared to last render.
  2. Step 2: Analyze options

    [propA, stateB] lists both dependencies separately, so effect runs if either changes.
    Options C and D use logical operators, which evaluate to single values and won't track changes properly.
    [] runs effect only once on mount.
  3. Final Answer:

    [propA, stateB] -> Option A
  4. Quick Check:

    List all dependencies separately in array [OK]
Hint: List each dependency separately in array to track changes [OK]
Common Mistakes:
  • Using logical operators inside dependency array
  • Leaving dependency array empty when dependencies exist
  • Assuming single combined value tracks all changes
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard