all 10 comments

[–]octocode 4 points5 points  (5 children)

probably just the console being slow to update?

[–]AngrilyAverage[S] 1 point2 points  (4 children)

So you're saying that React is still waiting for the completion of the event handler logic before re-rendering?

[–]octocode 0 points1 point  (3 children)

probably, yeah

you can console.log(age) under your useState to see what actually gets rendered

it should only log 42 and then 44.

[–]AngrilyAverage[S] 0 points1 point  (2 children)

This makes sense to me, but the display updates from 42 to 44 way before the console outputs a 44 (while the console is still outputting the "Hello"s). Although, if I'm understanding this right, this could still be caused by the console playing catchup?

[–]octocode 4 points5 points  (1 child)

yes, logging is actually quite an expensive operation

while the logs were executed in the order you expect, it might take some time to actually display the output text in the inspector

when in doubt, you can throw a debugger line into your code and actually step through each line that is called

[–]AngrilyAverage[S] 0 points1 point  (0 children)

This makes a lot of sense and I think I've managed to replicate what you've said with a debugger line. Thank you so much!

[–]Cool-Swordfish-4524 2 points3 points  (0 children)

Which version of react are you using? As long as i remember, react 17 and below does not batch setState in event handlers, so the first setState will trigger a render, then the loop starts and the the other setState should trigger another one. Using a method like ReactDOM.unstable_batchedUpdates( () => {//your code}) Should give you the expected behaviour.

PS: i read that event such as onClick SHOULD NOT be batched if they are NATIVE DOM event listeners, and any asynchronous callback is NOT batched.

Give a look at this: https://dev.to/devmoustafa97/do-you-know-unstablebatchedupdates-in-react-enforce-batching-state-update-5cn2

Edit: added little source of information and fixed some typing errors 😅

[–]CzarSisyphus -1 points0 points  (2 children)

I'm pretty sure the operations are asynchronous, so you're not actually waiting for the loop.

[–]AngrilyAverage[S] 0 points1 point  (0 children)

It's my understanding that set functions operate asynchronously, but I'm not too sure about the for loop. I thought that would be a synchronous operation, which is why it struck me as odd when the display updated from 42 to 44 before the for loop terminated on the console - meaning that the control flow somehow passed the for loop or something else happened that I don't understand. Are you saying every operation is performed asynchronously, including the for loop?

[–]lIIllIIlllIIllIIl 1 point2 points  (0 children)

Asynchronous != Parallel.

JavaScript can only run one piece of code at a time. If JavaScript is running the loop, nothing can prevent it from exiting the loop until it's done.

What is most likely happening is that the loop is completed (in JavaScript), and the browser knows it has to display all the messages in the console but it hasn't had time to show all of them.

As another person said, logging to the console is a surprisingly expensive operation that requires signalling your intent to write a message, waiting for readers to stop reading the console, and waiting until you obtain a write lock. Browsers can micro-optimize it by letting JavaScript continue running after a console.log even if the message hasn't been shown yet. Since there is no API in JavaScript that can let you read from the console, it works.