Add isRootDehydrated function
Currently this does nothing except read a boolean field, but I'm about to change this logic. Since this is accessed by React DOM, too, I put the function in a separate module that can be deep imported. Previously, it was accessing the FiberRoot directly. The reason it's a separate module is to break a circular dependency between React DOM and the reconciler.
Andrew Clark committed
Mar 4, 2022 at 12:37 UTC
83b941a519f0528f3c7938f2bc6094a8de60c21e
13 files changed
+45
-16
packages/react-dom/src/events/ReactDOMEventListener.js
+2
-1
@@ -53,6 +53,7 @@ import {
53
setCurrentUpdatePriority,
54
} from 'react-reconciler/src/ReactEventPriorities';
55
import ReactSharedInternals from 'shared/ReactSharedInternals';
56
+import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';
57
58
const {ReactCurrentBatchConfig} = ReactSharedInternals;
59
@@ -386,7 +387,7 @@ export function findInstanceBlockingEvent(
387
targetInst = null;
388
} else if (tag === HostRoot) {
389
const root: FiberRoot = nearestMounted.stateNode;
389
- if (root.isDehydrated) {
390
+ if (isRootDehydrated(root)) {
391
// If this happens during a replay something went wrong and it might block
392
// the whole system.
393
return getContainerFromFiber(nearestMounted);
packages/react-dom/src/events/ReactDOMEventReplaying.js
+2
-1
@@ -39,6 +39,7 @@ import {
39
} from '../client/ReactDOMComponentTree';
40
import {HostRoot, SuspenseComponent} from 'react-reconciler/src/ReactWorkTags';
41
import {isHigherEventPriority} from 'react-reconciler/src/ReactEventPriorities';
42
+import {isRootDehydrated} from 'react-reconciler/src/ReactFiberShellHydration';
43
44
let _attemptSynchronousHydration: (fiber: Object) => void;
45
@@ -414,7 +415,7 @@ function attemptExplicitHydrationTarget(
415
}
416
} else if (tag === HostRoot) {
417
const root: FiberRoot = nearestMounted.stateNode;
417
- if (root.isDehydrated) {
418
+ if (isRootDehydrated(root)) {
419
queuedTarget.blockedOn = getContainerFromFiber(nearestMounted);
420
// We don't currently have a way to increase the priority of
421
// a root other than sync.
packages/react-reconciler/src/ReactFiberBeginWork.new.js
+2
-1
@@ -223,6 +223,7 @@ import {
223
createOffscreenHostContainerFiber,
224
isSimpleFunctionComponent,
225
} from './ReactFiber.new';
226
+import {isRootDehydrated} from './ReactFiberShellHydration';
227
import {
228
retryDehydratedSuspenseBoundary,
229
scheduleUpdateOnFiber,
@@ -1351,7 +1352,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1352
resetHydrationState();
1353
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
1354
}
1354
- if (root.isDehydrated && enterHydrationState(workInProgress)) {
1355
+ if (isRootDehydrated(root) && enterHydrationState(workInProgress)) {
1356
// If we don't have any current children this might be the first pass.
1357
// We always try to hydrate. If this isn't a hydration pass there won't
1358
// be any children to hydrate which is effectively the same thing as
packages/react-reconciler/src/ReactFiberBeginWork.old.js
+2
-1
@@ -223,6 +223,7 @@ import {
223
createOffscreenHostContainerFiber,
224
isSimpleFunctionComponent,
225
} from './ReactFiber.old';
226
+import {isRootDehydrated} from './ReactFiberShellHydration';
227
import {
228
retryDehydratedSuspenseBoundary,
229
scheduleUpdateOnFiber,
@@ -1351,7 +1352,7 @@ function updateHostRoot(current, workInProgress, renderLanes) {
1352
resetHydrationState();
1353
return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);
1354
}
1354
- if (root.isDehydrated && enterHydrationState(workInProgress)) {
1355
+ if (isRootDehydrated(root) && enterHydrationState(workInProgress)) {
1356
// If we don't have any current children this might be the first pass.
1357
// We always try to hydrate. If this isn't a hydration pass there won't
1358
// be any children to hydrate which is effectively the same thing as
packages/react-reconciler/src/ReactFiberCommitWork.new.js
+3
-2
@@ -82,6 +82,7 @@ import {
82
Visibility,
83
} from './ReactFiberFlags';
84
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
85
+import {isRootDehydrated} from './ReactFiberShellHydration';
86
import {
87
resetCurrentFiber as resetCurrentDebugFiberInDEV,
88
setCurrentFiber as setCurrentDebugFiberInDEV,
@@ -1878,7 +1879,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1879
case HostRoot: {
1880
if (supportsHydration) {
1881
const root: FiberRoot = finishedWork.stateNode;
1881
- if (root.isDehydrated) {
1882
+ if (isRootDehydrated(root)) {
1883
// We've just hydrated. No need to hydrate again.
1884
root.isDehydrated = false;
1885
commitHydratedContainer(root.containerInfo);
@@ -1986,7 +1987,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1987
case HostRoot: {
1988
if (supportsHydration) {
1989
const root: FiberRoot = finishedWork.stateNode;
1989
- if (root.isDehydrated) {
1990
+ if (isRootDehydrated(root)) {
1991
// We've just hydrated. No need to hydrate again.
1992
root.isDehydrated = false;
1993
commitHydratedContainer(root.containerInfo);
packages/react-reconciler/src/ReactFiberCommitWork.old.js
+3
-2
@@ -82,6 +82,7 @@ import {
82
Visibility,
83
} from './ReactFiberFlags';
84
import getComponentNameFromFiber from 'react-reconciler/src/getComponentNameFromFiber';
85
+import {isRootDehydrated} from './ReactFiberShellHydration';
86
import {
87
resetCurrentFiber as resetCurrentDebugFiberInDEV,
88
setCurrentFiber as setCurrentDebugFiberInDEV,
@@ -1878,7 +1879,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1879
case HostRoot: {
1880
if (supportsHydration) {
1881
const root: FiberRoot = finishedWork.stateNode;
1881
- if (root.isDehydrated) {
1882
+ if (isRootDehydrated(root)) {
1883
// We've just hydrated. No need to hydrate again.
1884
root.isDehydrated = false;
1885
commitHydratedContainer(root.containerInfo);
@@ -1986,7 +1987,7 @@ function commitWork(current: Fiber | null, finishedWork: Fiber): void {
1987
case HostRoot: {
1988
if (supportsHydration) {
1989
const root: FiberRoot = finishedWork.stateNode;
1989
- if (root.isDehydrated) {
1990
+ if (isRootDehydrated(root)) {
1991
// We've just hydrated. No need to hydrate again.
1992
root.isDehydrated = false;
1993
commitHydratedContainer(root.containerInfo);
packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+2
-1
@@ -160,6 +160,7 @@ import {
160
includesSomeLane,
161
mergeLanes,
162
} from './ReactFiberLane.new';
163
+import {isRootDehydrated} from './ReactFiberShellHydration';
164
import {resetChildFibers} from './ReactChildFiber.new';
165
import {createScopeInstance} from './ReactFiberScope.new';
166
import {transferActualDuration} from './ReactProfilerTimer.new';
@@ -890,7 +891,7 @@ function completeWork(
891
// If we hydrated, then we'll need to schedule an update for
892
// the commit side-effects on the root.
893
markUpdate(workInProgress);
893
- } else if (!fiberRoot.isDehydrated) {
894
+ } else if (!isRootDehydrated(fiberRoot)) {
895
// Schedule an effect to clear this container at the start of the next commit.
896
// This handles the case of React rendering into a container with previous children.
897
// It's also safe to do for updates too, because current.child would only be null
packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+2
-1
@@ -160,6 +160,7 @@ import {
160
includesSomeLane,
161
mergeLanes,
162
} from './ReactFiberLane.old';
163
+import {isRootDehydrated} from './ReactFiberShellHydration';
164
import {resetChildFibers} from './ReactChildFiber.old';
165
import {createScopeInstance} from './ReactFiberScope.old';
166
import {transferActualDuration} from './ReactProfilerTimer.old';
@@ -890,7 +891,7 @@ function completeWork(
891
// If we hydrated, then we'll need to schedule an update for
892
// the commit side-effects on the root.
893
markUpdate(workInProgress);
893
- } else if (!fiberRoot.isDehydrated) {
894
+ } else if (!isRootDehydrated(fiberRoot)) {
895
// Schedule an effect to clear this container at the start of the next commit.
896
// This handles the case of React rendering into a container with previous children.
897
// It's also safe to do for updates too, because current.child would only be null
packages/react-reconciler/src/ReactFiberReconciler.new.js
+2
-1
@@ -48,6 +48,7 @@ import {
48
isContextProvider as isLegacyContextProvider,
49
} from './ReactFiberContext.new';
50
import {createFiberRoot} from './ReactFiberRoot.new';
51
+import {isRootDehydrated} from './ReactFiberShellHydration';
52
import {
53
injectInternals,
54
markRenderScheduled,
@@ -411,7 +412,7 @@ export function attemptSynchronousHydration(fiber: Fiber): void {
412
switch (fiber.tag) {
413
case HostRoot:
414
const root: FiberRoot = fiber.stateNode;
414
- if (root.isDehydrated) {
415
+ if (isRootDehydrated(root)) {
416
// Flush the first scheduled "update".
417
const lanes = getHighestPriorityPendingLanes(root);
418
flushRoot(root, lanes);
packages/react-reconciler/src/ReactFiberReconciler.old.js
+2
-1
@@ -48,6 +48,7 @@ import {
48
isContextProvider as isLegacyContextProvider,
49
} from './ReactFiberContext.old';
50
import {createFiberRoot} from './ReactFiberRoot.old';
51
+import {isRootDehydrated} from './ReactFiberShellHydration';
52
import {
53
injectInternals,
54
markRenderScheduled,
@@ -411,7 +412,7 @@ export function attemptSynchronousHydration(fiber: Fiber): void {
412
switch (fiber.tag) {
413
case HostRoot:
414
const root: FiberRoot = fiber.stateNode;
414
- if (root.isDehydrated) {
415
+ if (isRootDehydrated(root)) {
416
// Flush the first scheduled "update".
417
const lanes = getHighestPriorityPendingLanes(root);
418
flushRoot(root, lanes);
packages/react-reconciler/src/ReactFiberShellHydration.js
new
+17
@@ -0,0 +1,17 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import type {FiberRoot} from './ReactInternalTypes';
11
+
12
+// This is imported by the event replaying implementation in React DOM. It's
13
+// in a separate file to break a circular dependency between the renderer and
14
+// the reconciler.
15
+export function isRootDehydrated(root: FiberRoot) {
16
+ return root.isDehydrated;
17
+}
packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+3
-2
@@ -88,6 +88,7 @@ import {
88
createWorkInProgress,
89
assignFiberPropertiesInDEV,
90
} from './ReactFiber.new';
91
+import {isRootDehydrated} from './ReactFiberShellHydration';
92
import {NoMode, ProfileMode, ConcurrentMode} from './ReactTypeOfMode';
93
import {
94
HostRoot,
@@ -581,7 +582,7 @@ export function scheduleUpdateOnFiber(
582
}
583
}
584
584
- if (root.isDehydrated && root.tag !== LegacyRoot) {
585
+ if (isRootDehydrated(root) && root.tag !== LegacyRoot) {
586
// This root's shell hasn't hydrated yet. Revert to client rendering.
587
if (workInProgressRoot === root) {
588
// If this happened during an interleaved event, interrupt the
@@ -1016,7 +1017,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
1017
function recoverFromConcurrentError(root, errorRetryLanes) {
1018
// If an error occurred during hydration, discard server response and fall
1019
// back to client side render.
1019
- if (root.isDehydrated) {
1020
+ if (isRootDehydrated(root)) {
1021
root.isDehydrated = false;
1022
if (__DEV__) {
1023
errorHydratingContainer(root.containerInfo);
packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+3
-2
@@ -88,6 +88,7 @@ import {
88
createWorkInProgress,
89
assignFiberPropertiesInDEV,
90
} from './ReactFiber.old';
91
+import {isRootDehydrated} from './ReactFiberShellHydration';
92
import {NoMode, ProfileMode, ConcurrentMode} from './ReactTypeOfMode';
93
import {
94
HostRoot,
@@ -581,7 +582,7 @@ export function scheduleUpdateOnFiber(
582
}
583
}
584
584
- if (root.isDehydrated && root.tag !== LegacyRoot) {
585
+ if (isRootDehydrated(root) && root.tag !== LegacyRoot) {
586
// This root's shell hasn't hydrated yet. Revert to client rendering.
587
if (workInProgressRoot === root) {
588
// If this happened during an interleaved event, interrupt the
@@ -1016,7 +1017,7 @@ function performConcurrentWorkOnRoot(root, didTimeout) {
1017
function recoverFromConcurrentError(root, errorRetryLanes) {
1018
// If an error occurred during hydration, discard server response and fall
1019
// back to client side render.
1019
- if (root.isDehydrated) {
1020
+ if (isRootDehydrated(root)) {
1021
root.isDehydrated = false;
1022
if (__DEV__) {
1023
errorHydratingContainer(root.containerInfo);