0

React processes state updates after event handlers have finished running but below code doesn't working like that it updating the state.

For loop is still executing so as per statement it won't update the state until event handlers have finished running.

import * as React from 'react';
import './style.css';

export default function App() {
  const [count, setCount] = React.useState(0);

  const eventHandler = () => {
    setCount((prev) => prev + 1);

    for (let i = 0; i < 1000; i++) {
      console.log(i);
    }

    console.log('end');
  };


  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
      <button onClick={eventHandler}>Click me</button>
      <p>
        count: {count}
      </p>
    </div>
  );
}
Akhil Rana
  • 145
  • 2
  • 12
  • Does this answer your question? [The useState set method is not reflecting a change immediately](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately) – Noam Feb 22 '23 at 09:21
  • No. In above code it's updating the state immediately but the function (eventHandler) is still in process. @Noam – Akhil Rana Feb 22 '23 at 09:27
  • Ah sorry, I misunderstood your question. However, what makes you believe that the state is updated immediately? – Noam Feb 22 '23 at 17:11
  • You can execute the above code and see the for loop is still executing but parallel state is also updated. But as per react docs state only update or trigger re-render again after event handlers have finished running. – Akhil Rana Feb 23 '23 at 02:33
  • https://beta.reactjs.org/learn/queueing-a-series-of-state-updates Look at bottom on 2nd point in Recap Summary! – Akhil Rana Feb 23 '23 at 02:34
  • 1
    I did execute it and the DOM is indeed not updated until the loop is over. Although, 1000 rounds take very little for a modern computer - use 1000000 and I believe you'll notice the delay. – Noam Feb 23 '23 at 08:43

1 Answers1

0

The React code is executed as you expected (the loop finishes first, the state is updated second), but the browser console output is delayed.

Delayed console logs

The browser console is a quite sophisticated tool these days, with syntax highlighting and many powerful assisting functionality.

The browser console doesn't simply execute a console.log() synchronously, but only recognizes that you want to print this value at this point in the code execution.

From this information, the console output is built "as quick as possible" in parallel to the main code execution, often formatted or modified according to what the browser deems helpful.

But if the printing into the console takes a lot of time, the main code always has priority, and the console output might become delayed, or even outdated.

You can add time stamps to verify this:

export default function App() {
    const [count, setCount] = React.useState(0);

    const eventHandler = () => {

        setCount( prev => prev + 1 );

        for( let i = 0; i < 1000; i++ ){
            console.log( performance.now(), i );
        }

        console.log('end');
    };

    return (
        <div>
            <button onClick={eventHandler}>Click me</button>
            <p>count: { count }</p>
            <p>now: { performance.now() }</p>
        </div>
    );
}

You will notice that the last timestamp in the console is lower than the timestamp on the page, even if the console prints it later.

Outdated console logs

For fun, you might want to play with this example:

const x = {
    data: 'some data',
};

console.log('x:', x);

const MyApp = props => {

    x.data = 'other data';

    return <button onClick={ () => {
        x.data = 'other data 2';
    }}>
        change x
    </button>;
};

You might expect x.data to be some data, the value at the time the console.log was executed. And probably you will indeed see Object { data: "some data" } in the console, but if you expand the object in the console, it will (probably) display data: "other data".

But it's not as easy as "the console just keeps a reference to the object". E.g. if you expand the object, the object stays fixed from there on, i.e. if you click the button "change x" now, the value stays data: "other data".

kca
  • 4,856
  • 1
  • 20
  • 41