skip to Main Content

I try understanding render, re-render and the process on react when updating state.
I read on this article: kentcdodds

I have Component like this.

function DelayedCounter() {
  const [count, setCount] = React.useState(0)
  console.log('DelayedCounter', count)
  function increment() {
    setTimeout(() => {
      console.log('increment', count)
      setCount(count + 1)
    }, 2000)
  }
  return <button onClick={increment}>{count}</button>
}

I tried clicking the button 3 times quickly. And this is the result on my Chrome browser.

increment 0
DelayedCounter 1
increment 0
DelayedCounter 1
increment 0

I know we can use prevState with callback function, but I am just wondering Why count’s state in parent’s component get updated to be 1? But inside the increment’s function the count’s state still being 0?

Could you explain it?
Thank you.

2

Answers


  1. I tried clicking the button 3 times quickly.

    Since the function has a setTimeout to perform its operation after two seconds then "quickly" was probably faster than that. So all three clicks took place from the same rendered component. At that time the value of count was 0, so all three instances of console.log('increment', count) output a value of 0.

    Why count’s state in parent’s component get updated to be 1?

    Same reason. All three clicks were based on a value of 0, and all three clicks incremented that value by 1. So all three of them set the state to 1.

    Basically, all three clicks did this:

    setTimeout(() => {
      console.log('increment', 0)
      setCount(0 + 1)
    }, 2000)
    

    Overall, I suspect you’re over-thinking it. React isn’t doing anything particularly special here. Forgetting React for a moment, just take a look at the operation being performed. count has a value of 0. Upon clicking your button, count won’t be updated for another two seconds. So if you click the button again before two seconds, why would count have been updated by then?

    Login or Signup to reply.
  2. In React, state updates are asynchronous. When you call setCount(count + 1) in the increment function, React does not immediately update the count state. Instead, it schedules an update and continues with the rest of the code. Therefore, when you log the count immediately after calling setCount, you might not see the updated state.

    Sequence of events in your code:

    1.You click the button.

    2.increment function is called.

    3.setTimeout is set for 2000 milliseconds, and the current value of count is captured (which is 0).

    4.You click the button again before the setTimeout fires.

    5.Another setTimeout is set with the current value of count (still 0).

    6.This process repeats for each click before the first setTimeout fires.

    7.After 2000 milliseconds, the first setTimeout fires. The log inside the callback shows "increment 0" because it captured the state at the time it was set.

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