In the React, if it is triggered by the React of event processing (such as through the onClick event handler), setState will rerender async. Otherwise setState will rerender sync.
It's a funny coincidence that you posted this, because just a couple of days ago, I noticed the same thing, and posted about it in the conversation here: https://github.com/developit/preact-www/pull/15. See my final comment in particular. It appears (based on what I mention there) that this is actually an intentional difference between Preact and React (it's something "added" to Preact, according to the documentation).
Ah so this can actually be traced back to 8.x changing the async mechanism from Promise#then() (Microtasks) to setTimeout(0). There's mounting evidence that we should switch back, especially given be negligible byte cost and Safari's Promise error swallowing no longer being an issue. Here's the commit that effected the change, we can essentially just revert it:
https://github.com/developit/preact/commit/78014124593997d749e50ea1291a3c18731f1fe4
With that in place setState() is obviously still async, but at it's infinitely faster - Microtasks are scheduled based on the stack, and in that regard they are non-blocking but not "async" as we think of it (event loop based, a tick, etc). I think it straddles both cases in the original issue here quite nicely.
Yes, reverting to microtask-based scheduling sounds perfect to me.
Happy to merge a PR, or I can just try to get it done. There's a bunch of things I need to tend to in this repo this week!
Most helpful comment
Ah so this can actually be traced back to
8.xchanging the async mechanism fromPromise#then()(Microtasks) tosetTimeout(0). There's mounting evidence that we should switch back, especially given be negligible byte cost and Safari's Promise error swallowing no longer being an issue. Here's the commit that effected the change, we can essentially just revert it:https://github.com/developit/preact/commit/78014124593997d749e50ea1291a3c18731f1fe4
With that in place
setState()is obviously still async, but at it's infinitely faster - Microtasks are scheduled based on the stack, and in that regard they are non-blocking but not "async" as we think of it (event loop based, a tick, etc). I think it straddles both cases in the original issue here quite nicely.