Skip to content

Commit

Permalink
act: Bypass microtask for "default sync" updates (#21740)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
acdlite committed Jun 24, 2021
1 parent 8426bb6 commit 27c9c95
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
9 changes: 8 additions & 1 deletion packages/react-reconciler/src/ReactFiberWorkLoop.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,14 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
}
if (supportsMicrotasks) {
// Flush the queue in a microtask.
scheduleMicrotask(flushSyncCallbacks);
if (__DEV__ && ReactCurrentActQueue.current !== null) {
// Inside `act`, use our internal `act` queue so that these get flushed
// at the end of the current scope even when using the sync version
// of `act`.
ReactCurrentActQueue.current.push(flushSyncCallbacks);
} else {
scheduleMicrotask(flushSyncCallbacks);
}
} else {
// Flush the queue in an Immediate task.
scheduleCallback(ImmediateSchedulerPriority, flushSyncCallbacks);
Expand Down
9 changes: 8 additions & 1 deletion packages/react-reconciler/src/ReactFiberWorkLoop.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,14 @@ function ensureRootIsScheduled(root: FiberRoot, currentTime: number) {
}
if (supportsMicrotasks) {
// Flush the queue in a microtask.
scheduleMicrotask(flushSyncCallbacks);
if (__DEV__ && ReactCurrentActQueue.current !== null) {
// Inside `act`, use our internal `act` queue so that these get flushed
// at the end of the current scope even when using the sync version
// of `act`.
ReactCurrentActQueue.current.push(flushSyncCallbacks);
} else {
scheduleMicrotask(flushSyncCallbacks);
}
} else {
// Flush the queue in an Immediate task.
scheduleCallback(ImmediateSchedulerPriority, flushSyncCallbacks);
Expand Down

0 comments on commit 27c9c95

Please sign in to comment.