145
import type {ThenableState} from './ReactFiberThenable';
146
import type {BatchConfigTransition} from './ReactFiberTracingMarkerComponent';
147
import {
148
- entangleAsyncAction,
148
peekEntangledActionLane,
149
peekEntangledActionThenable,
150
chainThenableValue,
152
import {HostTransitionContext} from './ReactFiberHostContext';
153
import {requestTransitionLane} from './ReactFiberRootScheduler';
154
import {isCurrentTreeHidden} from './ReactFiberHiddenContext';
155
+import {
156
+ notifyTransitionCallbacks,
157
+ requestCurrentTransition,
158
+} from './ReactFiberTransition';
159
160
const {ReactCurrentDispatcher, ReactCurrentBatchConfig} = ReactSharedInternals;
161
1322
} else {
1323
// This update does have sufficient priority.
1324
1322
- // Check if this update is part of a pending async action. If so,
1323
- // we'll need to suspend until the action has finished, so that it's
1324
- // batched together with future updates in the same action.
1325
- if (updateLane !== NoLane && updateLane === peekEntangledActionLane()) {
1326
- didReadFromEntangledAsyncAction = true;
1327
- }
1328
-
1325
// Check if this is an optimistic update.
1326
const revertLane = update.revertLane;
1327
if (!enableAsyncActions || revertLane === NoLane) {
1342
};
1343
newBaseQueueLast = newBaseQueueLast.next = clone;
1344
}
1345
+
1346
+ // Check if this update is part of a pending async action. If so,
1347
+ // we'll need to suspend until the action has finished, so that it's
1348
+ // batched together with future updates in the same action.
1349
+ if (updateLane === peekEntangledActionLane()) {
1350
+ didReadFromEntangledAsyncAction = true;
1351
+ }
1352
} else {
1353
// This is an optimistic update. If the "revert" priority is
1354
// sufficient, don't apply the update. Otherwise, apply the update,
1359
// has finished. Pretend the update doesn't exist by skipping
1360
// over it.
1361
update = update.next;
1362
+
1363
+ // Check if this update is part of a pending async action. If so,
1364
+ // we'll need to suspend until the action has finished, so that it's
1365
+ // batched together with future updates in the same action.
1366
+ if (revertLane === peekEntangledActionLane()) {
1367
+ didReadFromEntangledAsyncAction = true;
1368
+ }
1369
continue;
1370
} else {
1371
const clone: Update<S, A> = {
1974
1975
// This is a fork of startTransition
1976
const prevTransition = ReactCurrentBatchConfig.transition;
1967
- ReactCurrentBatchConfig.transition = ({}: BatchConfigTransition);
1968
- const currentTransition = ReactCurrentBatchConfig.transition;
1977
+ const currentTransition: BatchConfigTransition = {
1978
+ _callbacks: new Set<(BatchConfigTransition, mixed) => mixed>(),
1979
+ };
1980
+ ReactCurrentBatchConfig.transition = currentTransition;
1981
if (__DEV__) {
1982
ReactCurrentBatchConfig.transition._updatedFibers = new Set();
1983
}
1984
try {
1985
const returnValue = action(prevState, payload);
1986
+ notifyTransitionCallbacks(currentTransition, returnValue);
1987
+
1988
if (
1989
returnValue !== null &&
1990
typeof returnValue === 'object' &&
2003
() => finishRunningFormStateAction(actionQueue, (setState: any)),
2004
);
2005
1992
- entangleAsyncAction<Awaited<S>>(thenable);
2006
setState((thenable: any));
2007
} else {
2008
setState((returnValue: any));
2821
);
2822
2823
const prevTransition = ReactCurrentBatchConfig.transition;
2811
- const currentTransition: BatchConfigTransition = {};
2824
+ const currentTransition: BatchConfigTransition = {
2825
+ _callbacks: new Set<(BatchConfigTransition, mixed) => mixed>(),
2826
+ };
2827
2828
if (enableAsyncActions) {
2829
// We don't really need to use an optimistic update here, because we
2854
try {
2855
if (enableAsyncActions) {
2856
const returnValue = callback();
2857
+ notifyTransitionCallbacks(currentTransition, returnValue);
2858
2859
// Check if we're inside an async action scope. If so, we'll entangle
2860
// this new action with the existing scope.
2870
typeof returnValue.then === 'function'
2871
) {
2872
const thenable = ((returnValue: any): Thenable<mixed>);
2857
- entangleAsyncAction<mixed>(thenable);
2873
// Create a thenable that resolves to `finishedState` once the async
2874
// action has completed.
2875
const thenableForFinishedState = chainThenableValue(
3296
queue: UpdateQueue<S, A>,
3297
action: A,
3298
): void {
3299
+ const transition = requestCurrentTransition();
3300
+
3301
if (__DEV__) {
3285
- if (ReactCurrentBatchConfig.transition === null) {
3302
+ if (transition === null) {
3303
// An optimistic update occurred, but startTransition is not on the stack.
3304
// There are two likely scenarios.
3305
3340
lane: SyncLane,
3341
// After committing, the optimistic update is "reverted" using the same
3342
// lane as the transition it's associated with.
3326
- revertLane: requestTransitionLane(),
3343
+ revertLane: requestTransitionLane(transition),
3344
action,
3345
hasEagerState: false,
3346
eagerState: null,