Offscreen: Use JS stack to track hidden/unhidden subtree state (#21211)
Brian Vaughn committed
Apr 8, 2021 at 17:27 UTC
d389c54d179f8228d11b058141be4ddd02608abe
2 files changed
+56
-46
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+28
-23
@@ -156,9 +156,7 @@ if (__DEV__) {
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> = [];
159
let offscreenSubtreeWasHidden: boolean = false;
161
-const offscreenSubtreeWasHiddenStack: Array<boolean> = [];
160
161
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
162
@@ -2305,11 +2303,35 @@ function commitLayoutEffects_begin(
2303
const wasHidden = current !== null && current.memoizedState !== null;
2304
const isHidden = fiber.memoizedState !== null;
2305
2308
- offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
2309
- offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
2306
+ const newOffscreenSubtreeIsHidden =
2307
+ isHidden || offscreenSubtreeIsHidden;
2308
+ const newOffscreenSubtreeWasHidden =
2309
+ wasHidden || offscreenSubtreeWasHidden;
2310
2311
- offscreenSubtreeWasHiddenStack.push(wasHidden);
2312
- offscreenSubtreeIsHiddenStack.push(isHidden);
2311
+ if (
2312
+ newOffscreenSubtreeIsHidden !== offscreenSubtreeIsHidden ||
2313
+ newOffscreenSubtreeWasHidden !== offscreenSubtreeWasHidden
2314
+ ) {
2315
+ const prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;
2316
+ const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;
2317
+
2318
+ // Traverse the Offscreen subtree with the current Offscreen as the root.
2319
+ offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden;
2320
+ offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden;
2321
+ commitLayoutEffects_begin(
2322
+ fiber, // New root; bubble back up to here and stop.
2323
+ root,
2324
+ committedLanes,
2325
+ );
2326
+
2327
+ // Restore Offscreen state and resume in our-progress traversal.
2328
+ nextEffect = fiber;
2329
+ offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;
2330
+ offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
2331
+ commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
2332
+
2333
+ continue;
2334
+ }
2335
}
2336
}
2337
@@ -2350,23 +2372,6 @@ function commitLayoutMountEffects_complete(
2372
while (nextEffect !== null) {
2373
const fiber = nextEffect;
2374
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
-
2375
if (
2376
enableSuspenseLayoutEffectSemantics &&
2377
isModernRoot &&
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+28
-23
@@ -156,9 +156,7 @@ if (__DEV__) {
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> = [];
159
let offscreenSubtreeWasHidden: boolean = false;
161
-const offscreenSubtreeWasHiddenStack: Array<boolean> = [];
160
161
const PossiblyWeakSet = typeof WeakSet === 'function' ? WeakSet : Set;
162
@@ -2305,11 +2303,35 @@ function commitLayoutEffects_begin(
2303
const wasHidden = current !== null && current.memoizedState !== null;
2304
const isHidden = fiber.memoizedState !== null;
2305
2308
- offscreenSubtreeWasHidden = wasHidden || offscreenSubtreeWasHidden;
2309
- offscreenSubtreeIsHidden = isHidden || offscreenSubtreeIsHidden;
2306
+ const newOffscreenSubtreeIsHidden =
2307
+ isHidden || offscreenSubtreeIsHidden;
2308
+ const newOffscreenSubtreeWasHidden =
2309
+ wasHidden || offscreenSubtreeWasHidden;
2310
2311
- offscreenSubtreeWasHiddenStack.push(wasHidden);
2312
- offscreenSubtreeIsHiddenStack.push(isHidden);
2311
+ if (
2312
+ newOffscreenSubtreeIsHidden !== offscreenSubtreeIsHidden ||
2313
+ newOffscreenSubtreeWasHidden !== offscreenSubtreeWasHidden
2314
+ ) {
2315
+ const prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden;
2316
+ const prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;
2317
+
2318
+ // Traverse the Offscreen subtree with the current Offscreen as the root.
2319
+ offscreenSubtreeIsHidden = newOffscreenSubtreeIsHidden;
2320
+ offscreenSubtreeWasHidden = newOffscreenSubtreeWasHidden;
2321
+ commitLayoutEffects_begin(
2322
+ fiber, // New root; bubble back up to here and stop.
2323
+ root,
2324
+ committedLanes,
2325
+ );
2326
+
2327
+ // Restore Offscreen state and resume in our-progress traversal.
2328
+ nextEffect = fiber;
2329
+ offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;
2330
+ offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;
2331
+ commitLayoutMountEffects_complete(subtreeRoot, root, committedLanes);
2332
+
2333
+ continue;
2334
+ }
2335
}
2336
}
2337
@@ -2350,23 +2372,6 @@ function commitLayoutMountEffects_complete(
2372
while (nextEffect !== null) {
2373
const fiber = nextEffect;
2374
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
-
2375
if (
2376
enableSuspenseLayoutEffectSemantics &&
2377
isModernRoot &&