Skip to content

Commit df06c46

Browse files
committed
Remove Passive flag from "before mutation" phase
We don't need to visit passive effect nodes during before mutation. The only reason we were previously was to schedule the root-level passive effect callback as early as possible, but now that `subtreeFlags` exists, we can check that instead. This should reduce the amount of traversal during the commit phase, particularly when mounting or updating large trees that contain many passive effects.
1 parent c57fe4a commit df06c46

File tree

2 files changed

+18
-27
lines changed

2 files changed

+18
-27
lines changed

packages/react-reconciler/src/ReactFiberFlags.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ export const ForceUpdateForLegacySuspense = /* */ 0b000100000000000000;
4848
export const PassiveStatic = /* */ 0b001000000000000000;
4949

5050
// Union of side effect groupings as pertains to subtreeFlags
51-
export const BeforeMutationMask = /* */ 0b000000001100001010;
51+
// TODO: Don't need to visit Placement during BeforeMutation phase
52+
// TODO: Only need to visit Deletions during BeforeMutation phase if an element
53+
// is focused.
54+
export const BeforeMutationMask = /* */ 0b000000000100001010;
5255
export const MutationMask = /* */ 0b000000010010011110;
5356
export const LayoutMask = /* */ 0b000000000010100100;
5457
export const PassiveMask = /* */ 0b000000001000001000;

packages/react-reconciler/src/ReactFiberWorkLoop.new.js

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,6 +1880,20 @@ function commitRootImpl(root, renderPriorityLevel) {
18801880
NoFlags;
18811881

18821882
if (subtreeHasEffects || rootHasEffect) {
1883+
// If there are pending passive effects, schedule a callback to process them.
1884+
if (
1885+
(finishedWork.subtreeFlags & PassiveMask) !== NoFlags ||
1886+
(finishedWork.flags & PassiveMask) !== NoFlags
1887+
) {
1888+
if (!rootDoesHavePassiveEffects) {
1889+
rootDoesHavePassiveEffects = true;
1890+
scheduleCallback(NormalSchedulerPriority, () => {
1891+
flushPassiveEffects();
1892+
return null;
1893+
});
1894+
}
1895+
}
1896+
18831897
let previousLanePriority;
18841898
if (decoupleUpdatePriorityFromScheduler) {
18851899
previousLanePriority = getCurrentUpdateLanePriority();
@@ -1972,20 +1986,6 @@ function commitRootImpl(root, renderPriorityLevel) {
19721986
markLayoutEffectsStopped();
19731987
}
19741988

1975-
// If there are pending passive effects, schedule a callback to process them.
1976-
if (
1977-
(finishedWork.subtreeFlags & PassiveMask) !== NoFlags ||
1978-
(finishedWork.flags & PassiveMask) !== NoFlags
1979-
) {
1980-
if (!rootDoesHavePassiveEffects) {
1981-
rootDoesHavePassiveEffects = true;
1982-
scheduleCallback(NormalSchedulerPriority, () => {
1983-
flushPassiveEffects();
1984-
return null;
1985-
});
1986-
}
1987-
}
1988-
19891989
// Tell Scheduler to yield at the end of the frame, so the browser has an
19901990
// opportunity to paint.
19911991
requestPaint();
@@ -2181,18 +2181,6 @@ function commitBeforeMutationEffectsImpl(fiber: Fiber) {
21812181
commitBeforeMutationEffectOnFiber(current, fiber);
21822182
resetCurrentDebugFiberInDEV();
21832183
}
2184-
2185-
if ((flags & Passive) !== NoFlags) {
2186-
// If there are passive effects, schedule a callback to flush at
2187-
// the earliest opportunity.
2188-
if (!rootDoesHavePassiveEffects) {
2189-
rootDoesHavePassiveEffects = true;
2190-
scheduleCallback(NormalSchedulerPriority, () => {
2191-
flushPassiveEffects();
2192-
return null;
2193-
});
2194-
}
2195-
}
21962184
}
21972185

21982186
function commitBeforeMutationEffectsDeletions(deletions: Array<Fiber>) {

0 commit comments

Comments
 (0)