@samitouri / QOS-React / commits / 27c9c95e23

act: Bypass microtask for "default sync" updates (#21740)

When wrapping an update in act, instead of scheduling a microtask, we can add the task to our internal queue. The benefit is that the user doesn't have to await the act call. We can flush the work synchronously. This doesn't account for microtasks that are scheduled in userspace, of course, but it at least covers React's usage.

Andrew Clark committed Jun 23, 2021 at 20:32 UTC 27c9c95e23ddedb9163373950e364dd62038f6c0
2 files changed +16 -2
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+8 -1
@@ -692,7 +692,14 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
692 }
693 if (supportsMicrotasks) {
694 // Flush the queue in a microtask.
695 - scheduleMicrotask(flushSyncCallbacks);
695 + if (__DEV__ && ReactCurrentActQueue.current !== null) {
696 + // Inside `act`, use our internal `act` queue so that these get flushed
697 + // at the end of the current scope even when using the sync version
698 + // of `act`.
699 + ReactCurrentActQueue.current.push(flushSyncCallbacks);
700 + } else {
701 + scheduleMicrotask(flushSyncCallbacks);
702 + }
703 } else {
704 // Flush the queue in an Immediate task.
705 scheduleCallback(ImmediateSchedulerPriority, flushSyncCallbacks);
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+8 -1
@@ -692,7 +692,14 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
692 }
693 if (supportsMicrotasks) {
694 // Flush the queue in a microtask.
695 - scheduleMicrotask(flushSyncCallbacks);
695 + if (__DEV__ && ReactCurrentActQueue.current !== null) {
696 + // Inside `act`, use our internal `act` queue so that these get flushed
697 + // at the end of the current scope even when using the sync version
698 + // of `act`.
699 + ReactCurrentActQueue.current.push(flushSyncCallbacks);
700 + } else {
701 + scheduleMicrotask(flushSyncCallbacks);
702 + }
703 } else {
704 // Flush the queue in an Immediate task.
705 scheduleCallback(ImmediateSchedulerPriority, flushSyncCallbacks);