Skip to content

Commit 5284237

Browse files
author
Brian Vaughn
committed
Offscreen: Use JS stack to track hidden/unhidden subtree state
1 parent ee6a05c commit 5284237

File tree

2 files changed

+63
-58
lines changed

2 files changed

+63
-58
lines changed

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

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,7 @@ if (__DEV__) {
156156
// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.
157157
// Only used when enableSuspenseLayoutEffectSemantics is enabled.
158158
let offscreenSubtreeIsHidden: boolean = false;
159-
const offscreenSubtreeIsHiddenStack: Array<boolean> = [];
160159
let offscreenSubtreeWasHidden: boolean = false;
161-
const offscreenSubtreeWasHiddenStack: Array<boolean> = [];
162160

163161
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
164162

@@ -2283,6 +2281,9 @@ export function commitLayoutEffects(
22832281
committedLanes: Lanes,
22842282
): void {
22852283
nextEffect = finishedWork;
2284+
offscreenSubtreeIsHidden = false;
2285+
offscreenSubtreeWasHidden = false;
2286+
22862287
commitLayoutEffects_begin(finishedWork, root, committedLanes);
22872288
}
22882289

@@ -2305,11 +2306,35 @@ function commitLayoutEffects_begin(
23052306
const wasHidden = current !== null && current.memoizedState !== null;
23062307
const isHidden = fiber.memoizedState !== null;
23072308

2308-
offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
2309-
offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
2309+
const newOffscreenSubtreeIsHidden =
2310+
isHidden || offscreenSubtreeIsHidden;
2311+
const newOffscreenSubtreeWasHidden =
2312+
wasHidden || offscreenSubtreeWasHidden;
2313+
2314+
if (
2315+
newOffscreenSubtreeIsHidden !== offscreenSubtreeIsHidden ||
2316+
newOffscreenSubtreeWasHidden !== offscreenSubtreeWasHidden
2317+
) {
2318+
const prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;
2319+
const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;
2320+
2321+
nextEffect = fiber;
2322+
offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden;
2323+
offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden;
2324+
2325+
// Traverse the Offscreen subtree with the current Offscreen as the root.
2326+
commitLayoutEffects_begin(
2327+
fiber, // New root; bubble back up to here and stop.
2328+
root,
2329+
committedLanes,
2330+
);
2331+
2332+
nextEffect = fiber.sibling;
2333+
offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;
2334+
offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
23102335

2311-
offscreenSubtreeWasHiddenStack.push(wasHidden);
2312-
offscreenSubtreeIsHiddenStack.push(isHidden);
2336+
continue;
2337+
}
23132338
}
23142339
}
23152340

@@ -2350,23 +2375,6 @@ function commitLayoutMountEffects_complete(
23502375
while (nextEffect !== null) {
23512376
const fiber = nextEffect;
23522377

2353-
if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
2354-
if (fiber.tag === OffscreenComponent) {
2355-
offscreenSubtreeWasHiddenStack.pop();
2356-
offscreenSubtreeIsHiddenStack.pop();
2357-
offscreenSubtreeWasHidden =
2358-
offscreenSubtreeWasHiddenStack.length > 0 &&
2359-
offscreenSubtreeWasHiddenStack[
2360-
offscreenSubtreeWasHiddenStack.length - 1
2361-
];
2362-
offscreenSubtreeIsHidden =
2363-
offscreenSubtreeIsHiddenStack.length > 0 &&
2364-
offscreenSubtreeIsHiddenStack[
2365-
offscreenSubtreeIsHiddenStack.length - 1
2366-
];
2367-
}
2368-
}
2369-
23702378
if (
23712379
enableSuspenseLayoutEffectSemantics &&
23722380
isModernRoot &&

packages/react-reconciler/src/ReactFiberCommitWork.old.js

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,6 @@ if (__DEV__) {
152152
didWarnAboutUndefinedSnapshotBeforeUpdate = new Set();
153153
}
154154

155-
// Used during the commit phase to track the state of the Offscreen component stack.
156-
// Allows us to avoid traversing the return path to find the nearest Offscreen ancestor.
157-
// Only used when enableSuspenseLayoutEffectSemantics is enabled.
158-
let offscreenSubtreeIsHidden: boolean = false;
159-
const offscreenSubtreeIsHiddenStack: Array<boolean> = [];
160-
let offscreenSubtreeWasHidden: boolean = false;
161-
const offscreenSubtreeWasHiddenStack: Array<boolean> = [];
162-
163155
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
164156

165157
let nextEffect: Fiber | null = null;
@@ -2283,13 +2275,15 @@ export function commitLayoutEffects(
22832275
committedLanes: Lanes,
22842276
): void {
22852277
nextEffect = finishedWork;
2286-
commitLayoutEffects_begin(finishedWork, root, committedLanes);
2278+
commitLayoutEffects_begin(finishedWork, root, committedLanes, false, false);
22872279
}
22882280

22892281
function commitLayoutEffects_begin(
22902282
subtreeRoot: Fiber,
22912283
root: FiberRoot,
22922284
committedLanes: Lanes,
2285+
subtreeWasHidden: boolean,
2286+
subtreeIsHidden: boolean,
22932287
) {
22942288
// Suspense layout effects semantics don't change for legacy roots.
22952289
const isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode;
@@ -2305,11 +2299,24 @@ function commitLayoutEffects_begin(
23052299
const wasHidden = current !== null && current.memoizedState !== null;
23062300
const isHidden = fiber.memoizedState !== null;
23072301

2308-
offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
2309-
offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
2302+
const newOffscreenSubtreeWasHidden = wasHidden || subtreeWasHidden;
2303+
const newOffscreenSubtreeIsHidden = isHidden || subtreeIsHidden;
23102304

2311-
offscreenSubtreeWasHiddenStack.push(wasHidden);
2312-
offscreenSubtreeIsHiddenStack.push(isHidden);
2305+
if (
2306+
newOffscreenSubtreeWasHidden !== subtreeWasHidden ||
2307+
newOffscreenSubtreeIsHidden !== subtreeIsHidden
2308+
) {
2309+
// Traverse the Offscreen subtree with the current Offscreen as the root.
2310+
commitLayoutEffects_begin(
2311+
fiber, // New root; bubble back up to here and stop.
2312+
root,
2313+
committedLanes,
2314+
newOffscreenSubtreeWasHidden,
2315+
newOffscreenSubtreeIsHidden,
2316+
);
2317+
nextEffect = fiber.sibling;
2318+
continue;
2319+
}
23132320
}
23142321
}
23152322

@@ -2318,8 +2325,7 @@ function commitLayoutEffects_begin(
23182325
nextEffect = firstChild;
23192326
} else {
23202327
if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
2321-
const visibilityChanged =
2322-
!offscreenSubtreeIsHidden && offscreenSubtreeWasHidden;
2328+
const visibilityChanged = !subtreeIsHidden && subtreeWasHidden;
23232329
if (
23242330
visibilityChanged &&
23252331
(fiber.subtreeFlags & LayoutStatic) !== NoFlags &&
@@ -2334,7 +2340,13 @@ function commitLayoutEffects_begin(
23342340
}
23352341
}
23362342

2337-
commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
2343+
commitLayoutMountEffects_complete(
2344+
subtreeRoot,
2345+
root,
2346+
committedLanes,
2347+
subtreeWasHidden,
2348+
subtreeIsHidden,
2349+
);
23382350
}
23392351
}
23402352
}
@@ -2343,35 +2355,20 @@ function commitLayoutMountEffects_complete(
23432355
subtreeRoot: Fiber,
23442356
root: FiberRoot,
23452357
committedLanes: Lanes,
2358+
subtreeWasHidden: boolean,
2359+
subtreeIsHidden: boolean,
23462360
) {
23472361
// Suspense layout effects semantics don't change for legacy roots.
23482362
const isModernRoot = (subtreeRoot.mode & ConcurrentMode) !== NoMode;
23492363

23502364
while (nextEffect !== null) {
23512365
const fiber = nextEffect;
23522366

2353-
if (enableSuspenseLayoutEffectSemantics && isModernRoot) {
2354-
if (fiber.tag === OffscreenComponent) {
2355-
offscreenSubtreeWasHiddenStack.pop();
2356-
offscreenSubtreeIsHiddenStack.pop();
2357-
offscreenSubtreeWasHidden =
2358-
offscreenSubtreeWasHiddenStack.length > 0 &&
2359-
offscreenSubtreeWasHiddenStack[
2360-
offscreenSubtreeWasHiddenStack.length - 1
2361-
];
2362-
offscreenSubtreeIsHidden =
2363-
offscreenSubtreeIsHiddenStack.length > 0 &&
2364-
offscreenSubtreeIsHiddenStack[
2365-
offscreenSubtreeIsHiddenStack.length - 1
2366-
];
2367-
}
2368-
}
2369-
23702367
if (
23712368
enableSuspenseLayoutEffectSemantics &&
23722369
isModernRoot &&
2373-
offscreenSubtreeWasHidden &&
2374-
!offscreenSubtreeIsHidden
2370+
subtreeWasHidden &&
2371+
!subtreeIsHidden
23752372
) {
23762373
// Inside of an Offscreen subtree that changed visibility during this commit.
23772374
// If this subtree was hidden, layout effects will have already been destroyed (during mutation phase)

0 commit comments

Comments
 (0)