Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Get legacy ReactCurrentActQueue checks
  • Loading branch information
sebmarkbage committed Apr 3, 2024
commit 16a13260bcab5fca829e8a886aaac0f4f34de95f
27 changes: 20 additions & 7 deletions packages/react/src/ReactAct.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import type {RendererTask} from './ReactCurrentActQueue';
import ReactCurrentActQueue from './ReactCurrentActQueue';
import queueMacrotask from 'shared/enqueueTask';

import {disableLegacyMode} from 'shared/ReactFeatureFlags';

// `act` calls can be nested, so we track the depth. This represents the
// number of `act` scopes on the stack.
let actScopeDepth = 0;
Expand All @@ -38,7 +40,9 @@ export function act<T>(callback: () => T | Thenable<T>): Thenable<T> {
// `act` calls can be nested.
//
// If we're already inside an `act` scope, reuse the existing queue.
const prevIsBatchingLegacy = ReactCurrentActQueue.isBatchingLegacy;
const prevIsBatchingLegacy = !disableLegacyMode
? ReactCurrentActQueue.isBatchingLegacy
: false;
const prevActQueue = ReactCurrentActQueue.current;
const prevActScopeDepth = actScopeDepth;
actScopeDepth++;
Expand All @@ -48,7 +52,9 @@ export function act<T>(callback: () => T | Thenable<T>): Thenable<T> {
// set to `true` while the given callback is executed, not for updates
// triggered during an async event, because this is how the legacy
// implementation of `act` behaved.
ReactCurrentActQueue.isBatchingLegacy = true;
if (!disableLegacyMode) {
ReactCurrentActQueue.isBatchingLegacy = true;
}

let result;
// This tracks whether the `act` call is awaited. In certain cases, not
Expand All @@ -58,10 +64,13 @@ export function act<T>(callback: () => T | Thenable<T>): Thenable<T> {
// Reset this to `false` right before entering the React work loop. The
// only place we ever read this fields is just below, right after running
// the callback. So we don't need to reset after the callback runs.
ReactCurrentActQueue.didScheduleLegacyUpdate = false;
if (!disableLegacyMode) {
ReactCurrentActQueue.didScheduleLegacyUpdate = false;
}
result = callback();
const didScheduleLegacyUpdate =
ReactCurrentActQueue.didScheduleLegacyUpdate;
const didScheduleLegacyUpdate = !disableLegacyMode
? ReactCurrentActQueue.didScheduleLegacyUpdate
: false;

// Replicate behavior of original `act` implementation in legacy mode,
// which flushed updates immediately after the scope function exits, even
Expand All @@ -73,7 +82,9 @@ export function act<T>(callback: () => T | Thenable<T>): Thenable<T> {
// one used to track `act` scopes. Why, you may be wondering? Because
// that's how it worked before version 18. Yes, it's confusing! We should
// delete legacy mode!!
ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy;
if (!disableLegacyMode) {
ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy;
}
} catch (error) {
// `isBatchingLegacy` gets reset using the regular stack, not the async
// one used to track `act` scopes. Why, you may be wondering? Because
Expand All @@ -82,7 +93,9 @@ export function act<T>(callback: () => T | Thenable<T>): Thenable<T> {
ReactCurrentActQueue.thrownErrors.push(error);
}
if (ReactCurrentActQueue.thrownErrors.length > 0) {
ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy;
if (!disableLegacyMode) {
ReactCurrentActQueue.isBatchingLegacy = prevIsBatchingLegacy;
}
popActScope(prevActQueue, prevActScopeDepth);
const thrownError = aggregateErrors(ReactCurrentActQueue.thrownErrors);
ReactCurrentActQueue.thrownErrors.length = 0;
Expand Down