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

Function act

packages/react/src/ReactAct.js:32–254  ·  packages/react/src/ReactAct.js::act
(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 class="cm">// When ReactSharedInternals.actQueue is not null, it signals to React that
35 class="cm">// we're currently inside an `act` scope. React will push all its tasks to
36 class="cm">// this queue instead of scheduling them with platform APIs.
37 class="cm">//
38 class="cm">// We set this to an empty array when we first enter an `act` scope, and
39 class="cm">// only unset it once we've left the outermost `act` scope — remember that
40 class="cm">// `act` calls can be nested.
41 class="cm">//
42 class="cm">// 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 class="cm">// Used to reproduce behavior of `batchedUpdates` in legacy mode. Only
52 class="cm">// set to `true` while the given callback is executed, not for updates
53 class="cm">// triggered during an async event, because this is how the legacy
54 class="cm">// implementation of `act` behaved.
55 if (!disableLegacyMode) {
56 ReactSharedInternals.isBatchingLegacy = true;
57 }
58
59 let result;
60 class="cm">// This tracks whether the `act` call is awaited. In certain cases, not
61 class="cm">// awaiting it is a mistake, so we will detect that and warn.
62 let didAwaitActCall = false;
63 try {
64 class="cm">// Reset this to `false` right before entering the React work loop. The
65 class="cm">// only place we ever read this fields is just below, right after running
66 class="cm">// 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 class="cm">// Replicate behavior of original `act` implementation in legacy mode,
76 class="cm">// which flushed updates immediately after the scope function exits, even
77 class="cm">// if it's an async function.
78 if (!prevIsBatchingLegacy && didScheduleLegacyUpdate) {
79 flushActQueue(queue);
80 }
81 class="cm">// `isBatchingLegacy` gets reset using the regular stack, not the async
82 class="cm">// one used to track `act` scopes. Why, you may be wondering? Because
83 class="cm">// thatclass="st">'s how it worked before version 18. Yes, it's confusing! We should
84 class="cm">// delete legacy mode!!
85 if (!disableLegacyMode) {
86 ReactSharedInternals.isBatchingLegacy = prevIsBatchingLegacy;
87 }
88 } catch (error) {
89 class="cm">// `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