skip to Main Content

In below code snippet, why is 2 logged after 3 & 4? I’m confused because if without the while loop, 2 would be logged before 3 & 4.

import React, { useState, useEffect } from 'react'
import ReactDOM from 'react-dom'

function App() {
  const [state] = useState(0)
  console.log(1)
  
  const start = Date.now()
  while (Date.now() - start < 50) {
    window.timestamp = Date.now()
  }
  
  useEffect(() => {
    console.log(2)
  }, [state])

  Promise.resolve().then(() => console.log(3))

  setTimeout(() => console.log(4), 0)

  return null
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>)

The correct log sequence is

1
3
4
2

See code in sandbox

2

Answers


  1. In the given code, the "2" is logged after "3" and "4" because the while loop blocks the main thread, delaying the execution of asynchronous code like promises and timeouts. Once the loop completes, these asynchronous tasks execute in the order they were queued, with "2" being logged last. Since useEffect(() => console.log(2), [state]) registers an effect to log "2" when the state variable changes. However, since the state doesn’t change and the thread is blocked by the while loop, this effect is not executed yet.

    Login or Signup to reply.
  2. It happens because useEffect is fired after the component is mounted

    So the sequence of the actions is:

    1. Render component
    2. console.log(1) // => 1
    3. Resolved Promise // => 3
    4. That timeout that wait 0 millisecond and fire // => 4
    5. And in the very end when component mounted fires useEffect // => 2

    More info about useEffect can be found here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search