Skip to content

Commit fdfb6a8

Browse files
committed
Flush event replaying at the end of the commit
Outside the Commit execution context and before passive effects.
1 parent 3ddcd2a commit fdfb6a8

File tree

4 files changed

+30
-6
lines changed

4 files changed

+30
-6
lines changed

packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,10 @@ import {
9999
DOCUMENT_FRAGMENT_NODE,
100100
} from './HTMLNodeType';
101101

102-
import {retryIfBlockedOn} from '../events/ReactDOMEventReplaying';
102+
import {
103+
flushEventReplaying,
104+
retryIfBlockedOn,
105+
} from '../events/ReactDOMEventReplaying';
103106

104107
import {
105108
enableCreateEventHandleAPI,
@@ -3655,6 +3658,12 @@ export function commitHydratedSuspenseInstance(
36553658
retryIfBlockedOn(suspenseInstance);
36563659
}
36573660
3661+
export function flushHydrationEvents(): void {
3662+
if (enableHydrationChangeEvent) {
3663+
flushEventReplaying();
3664+
}
3665+
}
3666+
36583667
export function shouldDeleteUnhydratedTailInstances(
36593668
parentType: string,
36603669
): boolean {

packages/react-dom-bindings/src/events/ReactDOMEventReplaying.js

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -472,12 +472,19 @@ function replayUnblockedEvents() {
472472
}
473473
}
474474

475+
export function flushEventReplaying(): void {
476+
// Synchronously flush any event replaying so that it gets observed before
477+
// any new updates are applied.
478+
if (hasScheduledReplayAttempt) {
479+
replayUnblockedEvents();
480+
}
481+
}
482+
475483
export function queueChangeEvent(target: EventTarget): void {
476484
if (enableHydrationChangeEvent) {
477485
queuedChangeEventTargets.push(target);
478486
if (!hasScheduledReplayAttempt) {
479487
hasScheduledReplayAttempt = true;
480-
scheduleCallback(NormalPriority, replayUnblockedEvents);
481488
}
482489
}
483490
}
@@ -490,10 +497,12 @@ function scheduleCallbackIfUnblocked(
490497
queuedEvent.blockedOn = null;
491498
if (!hasScheduledReplayAttempt) {
492499
hasScheduledReplayAttempt = true;
493-
// Schedule a callback to attempt replaying as many events as are
494-
// now unblocked. This first might not actually be unblocked yet.
495-
// We could check it early to avoid scheduling an unnecessary callback.
496-
scheduleCallback(NormalPriority, replayUnblockedEvents);
500+
if (!enableHydrationChangeEvent) {
501+
// Schedule a callback to attempt replaying as many events as are
502+
// now unblocked. This first might not actually be unblocked yet.
503+
// We could check it early to avoid scheduling an unnecessary callback.
504+
scheduleCallback(NormalPriority, replayUnblockedEvents);
505+
}
497506
}
498507
}
499508
}

packages/react-reconciler/src/ReactFiberWorkLoop.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import {
109109
startGestureTransition,
110110
stopViewTransition,
111111
createViewTransitionInstance,
112+
flushHydrationEvents,
112113
} from './ReactFiberConfig';
113114

114115
import {createWorkInProgress, resetWorkInProgress} from './ReactFiber';
@@ -3859,6 +3860,10 @@ function flushSpawnedWork(): void {
38593860
}
38603861
}
38613862

3863+
// Eagerly flush any event replaying that we unblocked within this commit.
3864+
// This ensures that those are observed before we render any new changes.
3865+
flushHydrationEvents();
3866+
38623867
// If layout work was scheduled, flush it now.
38633868
flushSyncWorkOnAllRoots();
38643869

packages/react-reconciler/src/forks/ReactFiberConfig.custom.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ export const commitHydratedActivityInstance =
228228
export const commitHydratedSuspenseInstance =
229229
$$$config.commitHydratedSuspenseInstance;
230230
export const finalizeHydratedChildren = $$$config.finalizeHydratedChildren;
231+
export const flushHydrationEvents = $$$config.flushHydrationEvents;
231232
export const clearActivityBoundary = $$$config.clearActivityBoundary;
232233
export const clearSuspenseBoundary = $$$config.clearSuspenseBoundary;
233234
export const clearActivityBoundaryFromContainer =

0 commit comments

Comments
 (0)