MCPcopy
hub / github.com/facebook/react / act

Function act

packages/react/src/ReactAct.js:32–254  ·  view source on GitHub ↗
(callback: () => T | Thenable<T>)

Source from the content-addressed store, hash-verified

30}
31
32export function act<T>(callback: () => T | Thenable<T>): Thenable<T> {
33 if (__DEV__) {
34 // When ReactSharedInternals.actQueue is not null, it signals to React that
35 // we're currently inside an `act` scope. React will push all its tasks to
36 // this queue instead of scheduling them with platform APIs.
37 //
38 // We set this to an empty array when we first enter an `act` scope, and
39 // only unset it once we've left the outermost `act` scope — remember that
40 // `act` calls can be nested.
41 //
42 // If we're already inside an `act` scope, reuse the existing queue.
43 const prevIsBatchingLegacy = !disableLegacyMode
44 ? ReactSharedInternals.isBatchingLegacy
45 : false;
46 const prevActQueue = ReactSharedInternals.actQueue;
47 const prevActScopeDepth = actScopeDepth;
48 actScopeDepth++;
49 const queue = (ReactSharedInternals.actQueue =
50 prevActQueue !== null ? prevActQueue : []);
51 // Used to reproduce behavior of `batchedUpdates` in legacy mode. Only
52 // set to `true` while the given callback is executed, not for updates
53 // triggered during an async event, because this is how the legacy
54 // implementation of `act` behaved.
55 if (!disableLegacyMode) {
56 ReactSharedInternals.isBatchingLegacy = true;
57 }
58
59 let result;
60 // This tracks whether the `act` call is awaited. In certain cases, not
61 // awaiting it is a mistake, so we will detect that and warn.
62 let didAwaitActCall = false;
63 try {
64 // Reset this to `false` right before entering the React work loop. The
65 // only place we ever read this fields is just below, right after running
66 // the callback. So we don't need to reset after the callback runs.
67 if (!disableLegacyMode) {
68 ReactSharedInternals.didScheduleLegacyUpdate = false;
69 }
70 result = callback();
71 const didScheduleLegacyUpdate = !disableLegacyMode
72 ? ReactSharedInternals.didScheduleLegacyUpdate
73 : false;
74
75 // Replicate behavior of original `act` implementation in legacy mode,
76 // which flushed updates immediately after the scope function exits, even
77 // if it's an async function.
78 if (!prevIsBatchingLegacy && didScheduleLegacyUpdate) {
79 flushActQueue(queue);
80 }
81 // `isBatchingLegacy` gets reset using the regular stack, not the async
82 // one used to track `act` scopes. Why, you may be wondering? Because
83 // that's how it worked before version 18. Yes, it's confusing! We should
84 // delete legacy mode!!
85 if (!disableLegacyMode) {
86 ReactSharedInternals.isBatchingLegacy = prevIsBatchingLegacy;
87 }
88 } catch (error) {
89 // `isBatchingLegacy` gets reset using the regular stack, not the async

Calls 6

flushActQueueFunction · 0.85
popActScopeFunction · 0.85
aggregateErrorsFunction · 0.70
pushMethod · 0.65
errorMethod · 0.65
callbackFunction · 0.50

Tested by 1

renderMethod · 0.40