diff --git a/packages/react-dom/src/__tests__/ReactServerRendering-test.js b/packages/react-dom/src/__tests__/ReactServerRendering-test.js
index 0c057c5fade05..23be43a7735a5 100644
--- a/packages/react-dom/src/__tests__/ReactServerRendering-test.js
+++ b/packages/react-dom/src/__tests__/ReactServerRendering-test.js
@@ -14,8 +14,6 @@ let React;
let ReactDOMServer;
let PropTypes;
let ReactCurrentDispatcher;
-const enableSuspenseServerRenderer = require('shared/ReactFeatureFlags')
- .enableSuspenseServerRenderer;
describe('ReactDOMServer', () => {
beforeEach(() => {
@@ -678,41 +676,6 @@ describe('ReactDOMServer', () => {
expect(markup).toBe('
');
});
- if (!enableSuspenseServerRenderer) {
- it('throws for unsupported types on the server', () => {
- expect(() => {
- ReactDOMServer.renderToString();
- }).toThrow('ReactDOMServer does not yet support Suspense.');
-
- async function fakeImport(result) {
- return {default: result};
- }
-
- expect(() => {
- const LazyFoo = React.lazy(() =>
- fakeImport(
- new Promise(resolve =>
- resolve(function Foo() {
- return ;
- }),
- ),
- ),
- );
- ReactDOMServer.renderToString();
- }).toThrow('ReactDOMServer does not yet support Suspense.');
- });
-
- it('throws when suspending on the server', () => {
- function AsyncFoo() {
- throw new Promise(() => {});
- }
-
- expect(() => {
- ReactDOMServer.renderToString();
- }).toThrow('ReactDOMServer does not yet support Suspense.');
- });
- }
-
it('does not get confused by throwing null', () => {
function Bad() {
// eslint-disable-next-line no-throw-literal
diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js
index d27bdff4305ab..0cf031776399e 100644
--- a/packages/react-dom/src/client/ReactDOMHostConfig.js
+++ b/packages/react-dom/src/client/ReactDOMHostConfig.js
@@ -63,7 +63,6 @@ import {retryIfBlockedOn} from '../events/ReactDOMEventReplaying';
import {
enableClientRenderFallbackOnHydrationMismatch,
- enableSuspenseServerRenderer,
enableCreateEventHandleAPI,
enableScopeAPI,
} from 'shared/ReactFeatureFlags';
@@ -747,19 +746,17 @@ function getNextHydratable(node) {
if (nodeType === ELEMENT_NODE || nodeType === TEXT_NODE) {
break;
}
- if (enableSuspenseServerRenderer) {
- if (nodeType === COMMENT_NODE) {
- const nodeData = (node: any).data;
- if (
- nodeData === SUSPENSE_START_DATA ||
- nodeData === SUSPENSE_FALLBACK_START_DATA ||
- nodeData === SUSPENSE_PENDING_START_DATA
- ) {
- break;
- }
- if (nodeData === SUSPENSE_END_DATA) {
- return null;
- }
+ if (nodeType === COMMENT_NODE) {
+ const nodeData = (node: any).data;
+ if (
+ nodeData === SUSPENSE_START_DATA ||
+ nodeData === SUSPENSE_FALLBACK_START_DATA ||
+ nodeData === SUSPENSE_PENDING_START_DATA
+ ) {
+ break;
+ }
+ if (nodeData === SUSPENSE_END_DATA) {
+ return null;
}
}
}
diff --git a/packages/react-dom/src/server/ReactPartialRenderer.js b/packages/react-dom/src/server/ReactPartialRenderer.js
index 41c2885680437..03f5355ef0e77 100644
--- a/packages/react-dom/src/server/ReactPartialRenderer.js
+++ b/packages/react-dom/src/server/ReactPartialRenderer.js
@@ -21,7 +21,6 @@ import {
warnAboutDeprecatedLifecycles,
disableLegacyContext,
disableModulePatternComponents,
- enableSuspenseServerRenderer,
enableScopeAPI,
} from 'shared/ReactFeatureFlags';
import {
@@ -965,21 +964,17 @@ class ReactDOMServerRenderer {
outBuffer += this.render(child, frame.context, frame.domNamespace);
} catch (err) {
if (err != null && typeof err.then === 'function') {
- if (enableSuspenseServerRenderer) {
- if (this.suspenseDepth <= 0) {
- throw new Error(
- // TODO: include component name. This is a bit tricky with current factoring.
- 'A React component suspended while rendering, but no fallback UI was specified.\n' +
- '\n' +
- 'Add a component higher in the tree to ' +
- 'provide a loading indicator or placeholder to display.',
- );
- }
-
- suspended = true;
- } else {
- throw new Error('ReactDOMServer does not yet support Suspense.');
+ if (this.suspenseDepth <= 0) {
+ throw new Error(
+ // TODO: include component name. This is a bit tricky with current factoring.
+ 'A React component suspended while rendering, but no fallback UI was specified.\n' +
+ '\n' +
+ 'Add a component higher in the tree to ' +
+ 'provide a loading indicator or placeholder to display.',
+ );
}
+
+ suspended = true;
} else {
throw err;
}
@@ -1097,39 +1092,35 @@ class ReactDOMServerRenderer {
return '';
}
case REACT_SUSPENSE_TYPE: {
- if (enableSuspenseServerRenderer) {
- const fallback = ((nextChild: any): ReactElement).props.fallback;
- const fallbackChildren = toArray(fallback);
- const nextChildren = toArray(
- ((nextChild: any): ReactElement).props.children,
- );
- const fallbackFrame: Frame = {
- type: null,
- domNamespace: parentNamespace,
- children: fallbackChildren,
- childIndex: 0,
- context: context,
- footer: '',
- };
- const frame: Frame = {
- fallbackFrame,
- type: REACT_SUSPENSE_TYPE,
- domNamespace: parentNamespace,
- children: nextChildren,
- childIndex: 0,
- context: context,
- footer: '',
- };
- if (__DEV__) {
- ((frame: any): FrameDev).debugElementStack = [];
- ((fallbackFrame: any): FrameDev).debugElementStack = [];
- }
- this.stack.push(frame);
- this.suspenseDepth++;
- return '';
- } else {
- throw new Error('ReactDOMServer does not yet support Suspense.');
+ const fallback = ((nextChild: any): ReactElement).props.fallback;
+ const fallbackChildren = toArray(fallback);
+ const nextChildren = toArray(
+ ((nextChild: any): ReactElement).props.children,
+ );
+ const fallbackFrame: Frame = {
+ type: null,
+ domNamespace: parentNamespace,
+ children: fallbackChildren,
+ childIndex: 0,
+ context: context,
+ footer: '',
+ };
+ const frame: Frame = {
+ fallbackFrame,
+ type: REACT_SUSPENSE_TYPE,
+ domNamespace: parentNamespace,
+ children: nextChildren,
+ childIndex: 0,
+ context: context,
+ footer: '',
+ };
+ if (__DEV__) {
+ ((frame: any): FrameDev).debugElementStack = [];
+ ((fallbackFrame: any): FrameDev).debugElementStack = [];
}
+ this.stack.push(frame);
+ this.suspenseDepth++;
+ return '';
}
// eslint-disable-next-line-no-fallthrough
case REACT_SCOPE_TYPE: {
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.new.js b/packages/react-reconciler/src/ReactFiberBeginWork.new.js
index 88876f05f7d8d..442c95b651250 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.new.js
@@ -96,7 +96,6 @@ import {
disableModulePatternComponents,
enableProfilerCommitHooks,
enableProfilerTimer,
- enableSuspenseServerRenderer,
warnAboutDefaultPropsOnFunctionComponents,
enableScopeAPI,
enableCache,
@@ -2134,17 +2133,15 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
// If we're currently hydrating, try to hydrate this boundary.
tryToClaimNextHydratableInstance(workInProgress);
// This could've been a dehydrated suspense component.
- if (enableSuspenseServerRenderer) {
- const suspenseState: null | SuspenseState = workInProgress.memoizedState;
- if (suspenseState !== null) {
- const dehydrated = suspenseState.dehydrated;
- if (dehydrated !== null) {
- return mountDehydratedSuspenseComponent(
- workInProgress,
- dehydrated,
- renderLanes,
- );
- }
+ const suspenseState: null | SuspenseState = workInProgress.memoizedState;
+ if (suspenseState !== null) {
+ const dehydrated = suspenseState.dehydrated;
+ if (dehydrated !== null) {
+ return mountDehydratedSuspenseComponent(
+ workInProgress,
+ dehydrated,
+ renderLanes,
+ );
}
}
@@ -2220,59 +2217,57 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
// The current tree is already showing a fallback
// Special path for hydration
- if (enableSuspenseServerRenderer) {
- const dehydrated = prevState.dehydrated;
- if (dehydrated !== null) {
- if (!didSuspend) {
- return updateDehydratedSuspenseComponent(
- current,
- workInProgress,
- dehydrated,
- prevState,
- renderLanes,
- );
- } else if (workInProgress.flags & ForceClientRender) {
- // Something errored during hydration. Try again without hydrating.
- workInProgress.flags &= ~ForceClientRender;
- return retrySuspenseComponentWithoutHydrating(
- current,
- workInProgress,
- renderLanes,
- new Error(
- 'There was an error while hydrating this Suspense boundary. ' +
- 'Switched to client rendering.',
- ),
- );
- } else if (
- (workInProgress.memoizedState: null | SuspenseState) !== null
- ) {
- // Something suspended and we should still be in dehydrated mode.
- // Leave the existing child in place.
- workInProgress.child = current.child;
- // The dehydrated completion pass expects this flag to be there
- // but the normal suspense pass doesn't.
- workInProgress.flags |= DidCapture;
- return null;
- } else {
- // Suspended but we should no longer be in dehydrated mode.
- // Therefore we now have to render the fallback.
- renderDidSuspendDelayIfPossible();
- const nextPrimaryChildren = nextProps.children;
- const nextFallbackChildren = nextProps.fallback;
- const fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(
- current,
- workInProgress,
- nextPrimaryChildren,
- nextFallbackChildren,
- renderLanes,
- );
- const primaryChildFragment: Fiber = (workInProgress.child: any);
- primaryChildFragment.memoizedState = mountSuspenseOffscreenState(
- renderLanes,
- );
- workInProgress.memoizedState = SUSPENDED_MARKER;
- return fallbackChildFragment;
- }
+ const dehydrated = prevState.dehydrated;
+ if (dehydrated !== null) {
+ if (!didSuspend) {
+ return updateDehydratedSuspenseComponent(
+ current,
+ workInProgress,
+ dehydrated,
+ prevState,
+ renderLanes,
+ );
+ } else if (workInProgress.flags & ForceClientRender) {
+ // Something errored during hydration. Try again without hydrating.
+ workInProgress.flags &= ~ForceClientRender;
+ return retrySuspenseComponentWithoutHydrating(
+ current,
+ workInProgress,
+ renderLanes,
+ new Error(
+ 'There was an error while hydrating this Suspense boundary. ' +
+ 'Switched to client rendering.',
+ ),
+ );
+ } else if (
+ (workInProgress.memoizedState: null | SuspenseState) !== null
+ ) {
+ // Something suspended and we should still be in dehydrated mode.
+ // Leave the existing child in place.
+ workInProgress.child = current.child;
+ // The dehydrated completion pass expects this flag to be there
+ // but the normal suspense pass doesn't.
+ workInProgress.flags |= DidCapture;
+ return null;
+ } else {
+ // Suspended but we should no longer be in dehydrated mode.
+ // Therefore we now have to render the fallback.
+ renderDidSuspendDelayIfPossible();
+ const nextPrimaryChildren = nextProps.children;
+ const nextFallbackChildren = nextProps.fallback;
+ const fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(
+ current,
+ workInProgress,
+ nextPrimaryChildren,
+ nextFallbackChildren,
+ renderLanes,
+ );
+ const primaryChildFragment: Fiber = (workInProgress.child: any);
+ primaryChildFragment.memoizedState = mountSuspenseOffscreenState(
+ renderLanes,
+ );
+ workInProgress.memoizedState = SUSPENDED_MARKER;
+ return fallbackChildFragment;
}
}
@@ -3657,20 +3652,18 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
case SuspenseComponent: {
const state: SuspenseState | null = workInProgress.memoizedState;
if (state !== null) {
- if (enableSuspenseServerRenderer) {
- if (state.dehydrated !== null) {
- pushSuspenseContext(
- workInProgress,
- setDefaultShallowSuspenseContext(suspenseStackCursor.current),
- );
- // We know that this component will suspend again because if it has
- // been unsuspended it has committed as a resolved Suspense component.
- // If it needs to be retried, it should have work scheduled on it.
- workInProgress.flags |= DidCapture;
- // We should never render the children of a dehydrated boundary until we
- // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork.
- return null;
- }
+ if (state.dehydrated !== null) {
+ pushSuspenseContext(
+ workInProgress,
+ setDefaultShallowSuspenseContext(suspenseStackCursor.current),
+ );
+ // We know that this component will suspend again because if it has
+ // been unsuspended it has committed as a resolved Suspense component.
+ // If it needs to be retried, it should have work scheduled on it.
+ workInProgress.flags |= DidCapture;
+ // We should never render the children of a dehydrated boundary until we
+ // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork.
+ return null;
}
// If this boundary is currently timed out, we need to decide
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.old.js b/packages/react-reconciler/src/ReactFiberBeginWork.old.js
index 418b714117e81..1632501b26db2 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.old.js
@@ -96,7 +96,6 @@ import {
disableModulePatternComponents,
enableProfilerCommitHooks,
enableProfilerTimer,
- enableSuspenseServerRenderer,
warnAboutDefaultPropsOnFunctionComponents,
enableScopeAPI,
enableCache,
@@ -2134,17 +2133,15 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
// If we're currently hydrating, try to hydrate this boundary.
tryToClaimNextHydratableInstance(workInProgress);
// This could've been a dehydrated suspense component.
- if (enableSuspenseServerRenderer) {
- const suspenseState: null | SuspenseState = workInProgress.memoizedState;
- if (suspenseState !== null) {
- const dehydrated = suspenseState.dehydrated;
- if (dehydrated !== null) {
- return mountDehydratedSuspenseComponent(
- workInProgress,
- dehydrated,
- renderLanes,
- );
- }
+ const suspenseState: null | SuspenseState = workInProgress.memoizedState;
+ if (suspenseState !== null) {
+ const dehydrated = suspenseState.dehydrated;
+ if (dehydrated !== null) {
+ return mountDehydratedSuspenseComponent(
+ workInProgress,
+ dehydrated,
+ renderLanes,
+ );
}
}
@@ -2220,59 +2217,57 @@ function updateSuspenseComponent(current, workInProgress, renderLanes) {
// The current tree is already showing a fallback
// Special path for hydration
- if (enableSuspenseServerRenderer) {
- const dehydrated = prevState.dehydrated;
- if (dehydrated !== null) {
- if (!didSuspend) {
- return updateDehydratedSuspenseComponent(
- current,
- workInProgress,
- dehydrated,
- prevState,
- renderLanes,
- );
- } else if (workInProgress.flags & ForceClientRender) {
- // Something errored during hydration. Try again without hydrating.
- workInProgress.flags &= ~ForceClientRender;
- return retrySuspenseComponentWithoutHydrating(
- current,
- workInProgress,
- renderLanes,
- new Error(
- 'There was an error while hydrating this Suspense boundary. ' +
- 'Switched to client rendering.',
- ),
- );
- } else if (
- (workInProgress.memoizedState: null | SuspenseState) !== null
- ) {
- // Something suspended and we should still be in dehydrated mode.
- // Leave the existing child in place.
- workInProgress.child = current.child;
- // The dehydrated completion pass expects this flag to be there
- // but the normal suspense pass doesn't.
- workInProgress.flags |= DidCapture;
- return null;
- } else {
- // Suspended but we should no longer be in dehydrated mode.
- // Therefore we now have to render the fallback.
- renderDidSuspendDelayIfPossible();
- const nextPrimaryChildren = nextProps.children;
- const nextFallbackChildren = nextProps.fallback;
- const fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(
- current,
- workInProgress,
- nextPrimaryChildren,
- nextFallbackChildren,
- renderLanes,
- );
- const primaryChildFragment: Fiber = (workInProgress.child: any);
- primaryChildFragment.memoizedState = mountSuspenseOffscreenState(
- renderLanes,
- );
- workInProgress.memoizedState = SUSPENDED_MARKER;
- return fallbackChildFragment;
- }
+ const dehydrated = prevState.dehydrated;
+ if (dehydrated !== null) {
+ if (!didSuspend) {
+ return updateDehydratedSuspenseComponent(
+ current,
+ workInProgress,
+ dehydrated,
+ prevState,
+ renderLanes,
+ );
+ } else if (workInProgress.flags & ForceClientRender) {
+ // Something errored during hydration. Try again without hydrating.
+ workInProgress.flags &= ~ForceClientRender;
+ return retrySuspenseComponentWithoutHydrating(
+ current,
+ workInProgress,
+ renderLanes,
+ new Error(
+ 'There was an error while hydrating this Suspense boundary. ' +
+ 'Switched to client rendering.',
+ ),
+ );
+ } else if (
+ (workInProgress.memoizedState: null | SuspenseState) !== null
+ ) {
+ // Something suspended and we should still be in dehydrated mode.
+ // Leave the existing child in place.
+ workInProgress.child = current.child;
+ // The dehydrated completion pass expects this flag to be there
+ // but the normal suspense pass doesn't.
+ workInProgress.flags |= DidCapture;
+ return null;
+ } else {
+ // Suspended but we should no longer be in dehydrated mode.
+ // Therefore we now have to render the fallback.
+ renderDidSuspendDelayIfPossible();
+ const nextPrimaryChildren = nextProps.children;
+ const nextFallbackChildren = nextProps.fallback;
+ const fallbackChildFragment = mountSuspenseFallbackAfterRetryWithoutHydrating(
+ current,
+ workInProgress,
+ nextPrimaryChildren,
+ nextFallbackChildren,
+ renderLanes,
+ );
+ const primaryChildFragment: Fiber = (workInProgress.child: any);
+ primaryChildFragment.memoizedState = mountSuspenseOffscreenState(
+ renderLanes,
+ );
+ workInProgress.memoizedState = SUSPENDED_MARKER;
+ return fallbackChildFragment;
}
}
@@ -3657,20 +3652,18 @@ function attemptEarlyBailoutIfNoScheduledUpdate(
case SuspenseComponent: {
const state: SuspenseState | null = workInProgress.memoizedState;
if (state !== null) {
- if (enableSuspenseServerRenderer) {
- if (state.dehydrated !== null) {
- pushSuspenseContext(
- workInProgress,
- setDefaultShallowSuspenseContext(suspenseStackCursor.current),
- );
- // We know that this component will suspend again because if it has
- // been unsuspended it has committed as a resolved Suspense component.
- // If it needs to be retried, it should have work scheduled on it.
- workInProgress.flags |= DidCapture;
- // We should never render the children of a dehydrated boundary until we
- // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork.
- return null;
- }
+ if (state.dehydrated !== null) {
+ pushSuspenseContext(
+ workInProgress,
+ setDefaultShallowSuspenseContext(suspenseStackCursor.current),
+ );
+ // We know that this component will suspend again because if it has
+ // been unsuspended it has committed as a resolved Suspense component.
+ // If it needs to be retried, it should have work scheduled on it.
+ workInProgress.flags |= DidCapture;
+ // We should never render the children of a dehydrated boundary until we
+ // upgrade it. We return null instead of bailoutOnAlreadyFinishedWork.
+ return null;
}
// If this boundary is currently timed out, we need to decide
diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.new.js b/packages/react-reconciler/src/ReactFiberCommitWork.new.js
index 2cb02b2a54664..6712e27bd28e1 100644
--- a/packages/react-reconciler/src/ReactFiberCommitWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberCommitWork.new.js
@@ -34,7 +34,6 @@ import {
enableProfilerCommitHooks,
enableProfilerNestedUpdatePhase,
enableSchedulingProfiler,
- enableSuspenseServerRenderer,
enableSuspenseCallback,
enableScopeAPI,
enableStrictEffects,
@@ -1652,33 +1651,31 @@ function commitDeletionEffectsOnFiber(
return;
}
case DehydratedFragment: {
- if (enableSuspenseServerRenderer) {
- if (enableSuspenseCallback) {
- const hydrationCallbacks = finishedRoot.hydrationCallbacks;
- if (hydrationCallbacks !== null) {
- const onDeleted = hydrationCallbacks.onDeleted;
- if (onDeleted) {
- onDeleted((deletedFiber.stateNode: SuspenseInstance));
- }
+ if (enableSuspenseCallback) {
+ const hydrationCallbacks = finishedRoot.hydrationCallbacks;
+ if (hydrationCallbacks !== null) {
+ const onDeleted = hydrationCallbacks.onDeleted;
+ if (onDeleted) {
+ onDeleted((deletedFiber.stateNode: SuspenseInstance));
}
}
+ }
- // Dehydrated fragments don't have any children
+ // Dehydrated fragments don't have any children
- // Delete the dehydrated suspense boundary and all of its content.
- if (supportsMutation) {
- if (hostParent !== null) {
- if (hostParentIsContainer) {
- clearSuspenseBoundaryFromContainer(
- ((hostParent: any): Container),
- (deletedFiber.stateNode: SuspenseInstance),
- );
- } else {
- clearSuspenseBoundary(
- ((hostParent: any): Instance),
- (deletedFiber.stateNode: SuspenseInstance),
- );
- }
+ // Delete the dehydrated suspense boundary and all of its content.
+ if (supportsMutation) {
+ if (hostParent !== null) {
+ if (hostParentIsContainer) {
+ clearSuspenseBoundaryFromContainer(
+ ((hostParent: any): Container),
+ (deletedFiber.stateNode: SuspenseInstance),
+ );
+ } else {
+ clearSuspenseBoundary(
+ ((hostParent: any): Instance),
+ (deletedFiber.stateNode: SuspenseInstance),
+ );
}
}
}
diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.old.js b/packages/react-reconciler/src/ReactFiberCommitWork.old.js
index fbd3873fa54fa..a00355b6f5fc8 100644
--- a/packages/react-reconciler/src/ReactFiberCommitWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberCommitWork.old.js
@@ -34,7 +34,6 @@ import {
enableProfilerCommitHooks,
enableProfilerNestedUpdatePhase,
enableSchedulingProfiler,
- enableSuspenseServerRenderer,
enableSuspenseCallback,
enableScopeAPI,
enableStrictEffects,
@@ -1652,33 +1651,31 @@ function commitDeletionEffectsOnFiber(
return;
}
case DehydratedFragment: {
- if (enableSuspenseServerRenderer) {
- if (enableSuspenseCallback) {
- const hydrationCallbacks = finishedRoot.hydrationCallbacks;
- if (hydrationCallbacks !== null) {
- const onDeleted = hydrationCallbacks.onDeleted;
- if (onDeleted) {
- onDeleted((deletedFiber.stateNode: SuspenseInstance));
- }
+ if (enableSuspenseCallback) {
+ const hydrationCallbacks = finishedRoot.hydrationCallbacks;
+ if (hydrationCallbacks !== null) {
+ const onDeleted = hydrationCallbacks.onDeleted;
+ if (onDeleted) {
+ onDeleted((deletedFiber.stateNode: SuspenseInstance));
}
}
+ }
- // Dehydrated fragments don't have any children
+ // Dehydrated fragments don't have any children
- // Delete the dehydrated suspense boundary and all of its content.
- if (supportsMutation) {
- if (hostParent !== null) {
- if (hostParentIsContainer) {
- clearSuspenseBoundaryFromContainer(
- ((hostParent: any): Container),
- (deletedFiber.stateNode: SuspenseInstance),
- );
- } else {
- clearSuspenseBoundary(
- ((hostParent: any): Instance),
- (deletedFiber.stateNode: SuspenseInstance),
- );
- }
+ // Delete the dehydrated suspense boundary and all of its content.
+ if (supportsMutation) {
+ if (hostParent !== null) {
+ if (hostParentIsContainer) {
+ clearSuspenseBoundaryFromContainer(
+ ((hostParent: any): Container),
+ (deletedFiber.stateNode: SuspenseInstance),
+ );
+ } else {
+ clearSuspenseBoundary(
+ ((hostParent: any): Instance),
+ (deletedFiber.stateNode: SuspenseInstance),
+ );
}
}
}
diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js
index 6beb7eadce375..683d29ab3c880 100644
--- a/packages/react-reconciler/src/ReactFiberCompleteWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberCompleteWork.new.js
@@ -138,7 +138,6 @@ import {
} from './ReactFiberHydrationContext.new';
import {
enableSuspenseCallback,
- enableSuspenseServerRenderer,
enableScopeAPI,
enableProfilerTimer,
enableCache,
@@ -1066,85 +1065,82 @@ function completeWork(
popSuspenseContext(workInProgress);
const nextState: null | SuspenseState = workInProgress.memoizedState;
- if (enableSuspenseServerRenderer) {
- if (
- enableClientRenderFallbackOnHydrationMismatch &&
- hasUnhydratedTailNodes() &&
- (workInProgress.mode & ConcurrentMode) !== NoMode &&
- (workInProgress.flags & DidCapture) === NoFlags
- ) {
- warnIfUnhydratedTailNodes(workInProgress);
- resetHydrationState();
- workInProgress.flags |=
- ForceClientRender | Incomplete | ShouldCapture;
- return workInProgress;
- }
- if (nextState !== null && nextState.dehydrated !== null) {
- // We might be inside a hydration state the first time we're picking up this
- // Suspense boundary, and also after we've reentered it for further hydration.
- const wasHydrated = popHydrationState(workInProgress);
- if (current === null) {
- if (!wasHydrated) {
- throw new Error(
- 'A dehydrated suspense component was completed without a hydrated node. ' +
- 'This is probably a bug in React.',
- );
- }
- prepareToHydrateHostSuspenseInstance(workInProgress);
- bubbleProperties(workInProgress);
- if (enableProfilerTimer) {
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- const isTimedOutSuspense = nextState !== null;
- if (isTimedOutSuspense) {
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
- const primaryChildFragment = workInProgress.child;
- if (primaryChildFragment !== null) {
- // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
- workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
- }
+ if (
+ enableClientRenderFallbackOnHydrationMismatch &&
+ hasUnhydratedTailNodes() &&
+ (workInProgress.mode & ConcurrentMode) !== NoMode &&
+ (workInProgress.flags & DidCapture) === NoFlags
+ ) {
+ warnIfUnhydratedTailNodes(workInProgress);
+ resetHydrationState();
+ workInProgress.flags |= ForceClientRender | Incomplete | ShouldCapture;
+ return workInProgress;
+ }
+ if (nextState !== null && nextState.dehydrated !== null) {
+ // We might be inside a hydration state the first time we're picking up this
+ // Suspense boundary, and also after we've reentered it for further hydration.
+ const wasHydrated = popHydrationState(workInProgress);
+ if (current === null) {
+ if (!wasHydrated) {
+ throw new Error(
+ 'A dehydrated suspense component was completed without a hydrated node. ' +
+ 'This is probably a bug in React.',
+ );
+ }
+ prepareToHydrateHostSuspenseInstance(workInProgress);
+ bubbleProperties(workInProgress);
+ if (enableProfilerTimer) {
+ if ((workInProgress.mode & ProfileMode) !== NoMode) {
+ const isTimedOutSuspense = nextState !== null;
+ if (isTimedOutSuspense) {
+ // Don't count time spent in a timed out Suspense subtree as part of the base duration.
+ const primaryChildFragment = workInProgress.child;
+ if (primaryChildFragment !== null) {
+ // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
+ workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
}
}
}
- return null;
- } else {
- // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration
- // state since we're now exiting out of it. popHydrationState doesn't do that for us.
- resetHydrationState();
- if ((workInProgress.flags & DidCapture) === NoFlags) {
- // This boundary did not suspend so it's now hydrated and unsuspended.
- workInProgress.memoizedState = null;
- }
- // If nothing suspended, we need to schedule an effect to mark this boundary
- // as having hydrated so events know that they're free to be invoked.
- // It's also a signal to replay events and the suspense callback.
- // If something suspended, schedule an effect to attach retry listeners.
- // So we might as well always mark this.
- workInProgress.flags |= Update;
- bubbleProperties(workInProgress);
- if (enableProfilerTimer) {
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- const isTimedOutSuspense = nextState !== null;
- if (isTimedOutSuspense) {
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
- const primaryChildFragment = workInProgress.child;
- if (primaryChildFragment !== null) {
- // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
- workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
- }
+ }
+ return null;
+ } else {
+ // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration
+ // state since we're now exiting out of it. popHydrationState doesn't do that for us.
+ resetHydrationState();
+ if ((workInProgress.flags & DidCapture) === NoFlags) {
+ // This boundary did not suspend so it's now hydrated and unsuspended.
+ workInProgress.memoizedState = null;
+ }
+ // If nothing suspended, we need to schedule an effect to mark this boundary
+ // as having hydrated so events know that they're free to be invoked.
+ // It's also a signal to replay events and the suspense callback.
+ // If something suspended, schedule an effect to attach retry listeners.
+ // So we might as well always mark this.
+ workInProgress.flags |= Update;
+ bubbleProperties(workInProgress);
+ if (enableProfilerTimer) {
+ if ((workInProgress.mode & ProfileMode) !== NoMode) {
+ const isTimedOutSuspense = nextState !== null;
+ if (isTimedOutSuspense) {
+ // Don't count time spent in a timed out Suspense subtree as part of the base duration.
+ const primaryChildFragment = workInProgress.child;
+ if (primaryChildFragment !== null) {
+ // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
+ workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
}
}
}
- return null;
}
+ return null;
}
-
- // Successfully completed this tree. If this was a forced client render,
- // there may have been recoverable errors during first hydration
- // attempt. If so, add them to a queue so we can log them in the
- // commit phase.
- upgradeHydrationErrorsToRecoverable();
}
+ // Successfully completed this tree. If this was a forced client render,
+ // there may have been recoverable errors during first hydration
+ // attempt. If so, add them to a queue so we can log them in the
+ // commit phase.
+ upgradeHydrationErrorsToRecoverable();
+
if ((workInProgress.flags & DidCapture) !== NoFlags) {
// Something suspended. Re-render with the fallback children.
workInProgress.lanes = renderLanes;
diff --git a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js
index fc9414efc2796..549e3da16b035 100644
--- a/packages/react-reconciler/src/ReactFiberCompleteWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberCompleteWork.old.js
@@ -138,7 +138,6 @@ import {
} from './ReactFiberHydrationContext.old';
import {
enableSuspenseCallback,
- enableSuspenseServerRenderer,
enableScopeAPI,
enableProfilerTimer,
enableCache,
@@ -1066,85 +1065,82 @@ function completeWork(
popSuspenseContext(workInProgress);
const nextState: null | SuspenseState = workInProgress.memoizedState;
- if (enableSuspenseServerRenderer) {
- if (
- enableClientRenderFallbackOnHydrationMismatch &&
- hasUnhydratedTailNodes() &&
- (workInProgress.mode & ConcurrentMode) !== NoMode &&
- (workInProgress.flags & DidCapture) === NoFlags
- ) {
- warnIfUnhydratedTailNodes(workInProgress);
- resetHydrationState();
- workInProgress.flags |=
- ForceClientRender | Incomplete | ShouldCapture;
- return workInProgress;
- }
- if (nextState !== null && nextState.dehydrated !== null) {
- // We might be inside a hydration state the first time we're picking up this
- // Suspense boundary, and also after we've reentered it for further hydration.
- const wasHydrated = popHydrationState(workInProgress);
- if (current === null) {
- if (!wasHydrated) {
- throw new Error(
- 'A dehydrated suspense component was completed without a hydrated node. ' +
- 'This is probably a bug in React.',
- );
- }
- prepareToHydrateHostSuspenseInstance(workInProgress);
- bubbleProperties(workInProgress);
- if (enableProfilerTimer) {
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- const isTimedOutSuspense = nextState !== null;
- if (isTimedOutSuspense) {
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
- const primaryChildFragment = workInProgress.child;
- if (primaryChildFragment !== null) {
- // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
- workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
- }
+ if (
+ enableClientRenderFallbackOnHydrationMismatch &&
+ hasUnhydratedTailNodes() &&
+ (workInProgress.mode & ConcurrentMode) !== NoMode &&
+ (workInProgress.flags & DidCapture) === NoFlags
+ ) {
+ warnIfUnhydratedTailNodes(workInProgress);
+ resetHydrationState();
+ workInProgress.flags |= ForceClientRender | Incomplete | ShouldCapture;
+ return workInProgress;
+ }
+ if (nextState !== null && nextState.dehydrated !== null) {
+ // We might be inside a hydration state the first time we're picking up this
+ // Suspense boundary, and also after we've reentered it for further hydration.
+ const wasHydrated = popHydrationState(workInProgress);
+ if (current === null) {
+ if (!wasHydrated) {
+ throw new Error(
+ 'A dehydrated suspense component was completed without a hydrated node. ' +
+ 'This is probably a bug in React.',
+ );
+ }
+ prepareToHydrateHostSuspenseInstance(workInProgress);
+ bubbleProperties(workInProgress);
+ if (enableProfilerTimer) {
+ if ((workInProgress.mode & ProfileMode) !== NoMode) {
+ const isTimedOutSuspense = nextState !== null;
+ if (isTimedOutSuspense) {
+ // Don't count time spent in a timed out Suspense subtree as part of the base duration.
+ const primaryChildFragment = workInProgress.child;
+ if (primaryChildFragment !== null) {
+ // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
+ workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
}
}
}
- return null;
- } else {
- // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration
- // state since we're now exiting out of it. popHydrationState doesn't do that for us.
- resetHydrationState();
- if ((workInProgress.flags & DidCapture) === NoFlags) {
- // This boundary did not suspend so it's now hydrated and unsuspended.
- workInProgress.memoizedState = null;
- }
- // If nothing suspended, we need to schedule an effect to mark this boundary
- // as having hydrated so events know that they're free to be invoked.
- // It's also a signal to replay events and the suspense callback.
- // If something suspended, schedule an effect to attach retry listeners.
- // So we might as well always mark this.
- workInProgress.flags |= Update;
- bubbleProperties(workInProgress);
- if (enableProfilerTimer) {
- if ((workInProgress.mode & ProfileMode) !== NoMode) {
- const isTimedOutSuspense = nextState !== null;
- if (isTimedOutSuspense) {
- // Don't count time spent in a timed out Suspense subtree as part of the base duration.
- const primaryChildFragment = workInProgress.child;
- if (primaryChildFragment !== null) {
- // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
- workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
- }
+ }
+ return null;
+ } else {
+ // We might have reentered this boundary to hydrate it. If so, we need to reset the hydration
+ // state since we're now exiting out of it. popHydrationState doesn't do that for us.
+ resetHydrationState();
+ if ((workInProgress.flags & DidCapture) === NoFlags) {
+ // This boundary did not suspend so it's now hydrated and unsuspended.
+ workInProgress.memoizedState = null;
+ }
+ // If nothing suspended, we need to schedule an effect to mark this boundary
+ // as having hydrated so events know that they're free to be invoked.
+ // It's also a signal to replay events and the suspense callback.
+ // If something suspended, schedule an effect to attach retry listeners.
+ // So we might as well always mark this.
+ workInProgress.flags |= Update;
+ bubbleProperties(workInProgress);
+ if (enableProfilerTimer) {
+ if ((workInProgress.mode & ProfileMode) !== NoMode) {
+ const isTimedOutSuspense = nextState !== null;
+ if (isTimedOutSuspense) {
+ // Don't count time spent in a timed out Suspense subtree as part of the base duration.
+ const primaryChildFragment = workInProgress.child;
+ if (primaryChildFragment !== null) {
+ // $FlowFixMe Flow doesn't support type casting in combination with the -= operator
+ workInProgress.treeBaseDuration -= ((primaryChildFragment.treeBaseDuration: any): number);
}
}
}
- return null;
}
+ return null;
}
-
- // Successfully completed this tree. If this was a forced client render,
- // there may have been recoverable errors during first hydration
- // attempt. If so, add them to a queue so we can log them in the
- // commit phase.
- upgradeHydrationErrorsToRecoverable();
}
+ // Successfully completed this tree. If this was a forced client render,
+ // there may have been recoverable errors during first hydration
+ // attempt. If so, add them to a queue so we can log them in the
+ // commit phase.
+ upgradeHydrationErrorsToRecoverable();
+
if ((workInProgress.flags & DidCapture) !== NoFlags) {
// Something suspended. Re-render with the fallback children.
workInProgress.lanes = renderLanes;
diff --git a/packages/react-reconciler/src/ReactFiberHydrationContext.new.js b/packages/react-reconciler/src/ReactFiberHydrationContext.new.js
index 94ca9e61eec15..98981e904a90a 100644
--- a/packages/react-reconciler/src/ReactFiberHydrationContext.new.js
+++ b/packages/react-reconciler/src/ReactFiberHydrationContext.new.js
@@ -68,10 +68,7 @@ import {
didNotFindHydratableTextInstance,
didNotFindHydratableSuspenseInstance,
} from './ReactFiberHostConfig';
-import {
- enableClientRenderFallbackOnHydrationMismatch,
- enableSuspenseServerRenderer,
-} from 'shared/ReactFeatureFlags';
+import {enableClientRenderFallbackOnHydrationMismatch} from 'shared/ReactFeatureFlags';
import {OffscreenLane} from './ReactFiberLane.new';
import {
getSuspendedTreeContext,
@@ -347,32 +344,30 @@ function tryHydrate(fiber, nextInstance) {
return false;
}
case SuspenseComponent: {
- if (enableSuspenseServerRenderer) {
- const suspenseInstance: null | SuspenseInstance = canHydrateSuspenseInstance(
- nextInstance,
+ const suspenseInstance: null | SuspenseInstance = canHydrateSuspenseInstance(
+ nextInstance,
+ );
+ if (suspenseInstance !== null) {
+ const suspenseState: SuspenseState = {
+ dehydrated: suspenseInstance,
+ treeContext: getSuspendedTreeContext(),
+ retryLane: OffscreenLane,
+ };
+ fiber.memoizedState = suspenseState;
+ // Store the dehydrated fragment as a child fiber.
+ // This simplifies the code for getHostSibling and deleting nodes,
+ // since it doesn't have to consider all Suspense boundaries and
+ // check if they're dehydrated ones or not.
+ const dehydratedFragment = createFiberFromDehydratedFragment(
+ suspenseInstance,
);
- if (suspenseInstance !== null) {
- const suspenseState: SuspenseState = {
- dehydrated: suspenseInstance,
- treeContext: getSuspendedTreeContext(),
- retryLane: OffscreenLane,
- };
- fiber.memoizedState = suspenseState;
- // Store the dehydrated fragment as a child fiber.
- // This simplifies the code for getHostSibling and deleting nodes,
- // since it doesn't have to consider all Suspense boundaries and
- // check if they're dehydrated ones or not.
- const dehydratedFragment = createFiberFromDehydratedFragment(
- suspenseInstance,
- );
- dehydratedFragment.return = fiber;
- fiber.child = dehydratedFragment;
- hydrationParentFiber = fiber;
- // While a Suspense Instance does have children, we won't step into
- // it during the first pass. Instead, we'll reenter it later.
- nextHydratableInstance = null;
- return true;
- }
+ dehydratedFragment.return = fiber;
+ fiber.child = dehydratedFragment;
+ hydrationParentFiber = fiber;
+ // While a Suspense Instance does have children, we won't step into
+ // it during the first pass. Instead, we'll reenter it later.
+ nextHydratableInstance = null;
+ return true;
}
return false;
}
diff --git a/packages/react-reconciler/src/ReactFiberHydrationContext.old.js b/packages/react-reconciler/src/ReactFiberHydrationContext.old.js
index 6af68fe66a79d..fd98256927847 100644
--- a/packages/react-reconciler/src/ReactFiberHydrationContext.old.js
+++ b/packages/react-reconciler/src/ReactFiberHydrationContext.old.js
@@ -68,10 +68,7 @@ import {
didNotFindHydratableTextInstance,
didNotFindHydratableSuspenseInstance,
} from './ReactFiberHostConfig';
-import {
- enableClientRenderFallbackOnHydrationMismatch,
- enableSuspenseServerRenderer,
-} from 'shared/ReactFeatureFlags';
+import {enableClientRenderFallbackOnHydrationMismatch} from 'shared/ReactFeatureFlags';
import {OffscreenLane} from './ReactFiberLane.old';
import {
getSuspendedTreeContext,
@@ -347,32 +344,30 @@ function tryHydrate(fiber, nextInstance) {
return false;
}
case SuspenseComponent: {
- if (enableSuspenseServerRenderer) {
- const suspenseInstance: null | SuspenseInstance = canHydrateSuspenseInstance(
- nextInstance,
+ const suspenseInstance: null | SuspenseInstance = canHydrateSuspenseInstance(
+ nextInstance,
+ );
+ if (suspenseInstance !== null) {
+ const suspenseState: SuspenseState = {
+ dehydrated: suspenseInstance,
+ treeContext: getSuspendedTreeContext(),
+ retryLane: OffscreenLane,
+ };
+ fiber.memoizedState = suspenseState;
+ // Store the dehydrated fragment as a child fiber.
+ // This simplifies the code for getHostSibling and deleting nodes,
+ // since it doesn't have to consider all Suspense boundaries and
+ // check if they're dehydrated ones or not.
+ const dehydratedFragment = createFiberFromDehydratedFragment(
+ suspenseInstance,
);
- if (suspenseInstance !== null) {
- const suspenseState: SuspenseState = {
- dehydrated: suspenseInstance,
- treeContext: getSuspendedTreeContext(),
- retryLane: OffscreenLane,
- };
- fiber.memoizedState = suspenseState;
- // Store the dehydrated fragment as a child fiber.
- // This simplifies the code for getHostSibling and deleting nodes,
- // since it doesn't have to consider all Suspense boundaries and
- // check if they're dehydrated ones or not.
- const dehydratedFragment = createFiberFromDehydratedFragment(
- suspenseInstance,
- );
- dehydratedFragment.return = fiber;
- fiber.child = dehydratedFragment;
- hydrationParentFiber = fiber;
- // While a Suspense Instance does have children, we won't step into
- // it during the first pass. Instead, we'll reenter it later.
- nextHydratableInstance = null;
- return true;
- }
+ dehydratedFragment.return = fiber;
+ fiber.child = dehydratedFragment;
+ hydrationParentFiber = fiber;
+ // While a Suspense Instance does have children, we won't step into
+ // it during the first pass. Instead, we'll reenter it later.
+ nextHydratableInstance = null;
+ return true;
}
return false;
}
diff --git a/packages/react-reconciler/src/ReactFiberNewContext.new.js b/packages/react-reconciler/src/ReactFiberNewContext.new.js
index 8f269a4050215..68862e568818f 100644
--- a/packages/react-reconciler/src/ReactFiberNewContext.new.js
+++ b/packages/react-reconciler/src/ReactFiberNewContext.new.js
@@ -42,7 +42,6 @@ import is from 'shared/objectIs';
import {createUpdate, ForceUpdate} from './ReactUpdateQueue.new';
import {markWorkInProgressReceivedUpdate} from './ReactFiberBeginWork.new';
import {
- enableSuspenseServerRenderer,
enableLazyContextPropagation,
enableServerContext,
} from 'shared/ReactFeatureFlags';
@@ -295,10 +294,7 @@ function propagateContextChange_eager(
} else if (fiber.tag === ContextProvider) {
// Don't scan deeper if this is a matching provider
nextFiber = fiber.type === workInProgress.type ? null : fiber.child;
- } else if (
- enableSuspenseServerRenderer &&
- fiber.tag === DehydratedFragment
- ) {
+ } else if (fiber.tag === DehydratedFragment) {
// If a dehydrated suspense boundary is in this subtree, we don't know
// if it will have any context consumers in it. The best we can do is
// mark it as having updates.
@@ -425,10 +421,7 @@ function propagateContextChanges(
}
dep = dependency.next;
}
- } else if (
- enableSuspenseServerRenderer &&
- fiber.tag === DehydratedFragment
- ) {
+ } else if (fiber.tag === DehydratedFragment) {
// If a dehydrated suspense boundary is in this subtree, we don't know
// if it will have any context consumers in it. The best we can do is
// mark it as having updates.
diff --git a/packages/react-reconciler/src/ReactFiberNewContext.old.js b/packages/react-reconciler/src/ReactFiberNewContext.old.js
index a48c842043821..de96664e774a2 100644
--- a/packages/react-reconciler/src/ReactFiberNewContext.old.js
+++ b/packages/react-reconciler/src/ReactFiberNewContext.old.js
@@ -42,7 +42,6 @@ import is from 'shared/objectIs';
import {createUpdate, ForceUpdate} from './ReactUpdateQueue.old';
import {markWorkInProgressReceivedUpdate} from './ReactFiberBeginWork.old';
import {
- enableSuspenseServerRenderer,
enableLazyContextPropagation,
enableServerContext,
} from 'shared/ReactFeatureFlags';
@@ -295,10 +294,7 @@ function propagateContextChange_eager(
} else if (fiber.tag === ContextProvider) {
// Don't scan deeper if this is a matching provider
nextFiber = fiber.type === workInProgress.type ? null : fiber.child;
- } else if (
- enableSuspenseServerRenderer &&
- fiber.tag === DehydratedFragment
- ) {
+ } else if (fiber.tag === DehydratedFragment) {
// If a dehydrated suspense boundary is in this subtree, we don't know
// if it will have any context consumers in it. The best we can do is
// mark it as having updates.
@@ -425,10 +421,7 @@ function propagateContextChanges(
}
dep = dependency.next;
}
- } else if (
- enableSuspenseServerRenderer &&
- fiber.tag === DehydratedFragment
- ) {
+ } else if (fiber.tag === DehydratedFragment) {
// If a dehydrated suspense boundary is in this subtree, we don't know
// if it will have any context consumers in it. The best we can do is
// mark it as having updates.
diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js
index eb2ea2286a275..c97c3e2ebc166 100644
--- a/packages/react-reconciler/src/ReactFiberUnwindWork.new.js
+++ b/packages/react-reconciler/src/ReactFiberUnwindWork.new.js
@@ -28,11 +28,7 @@ import {
} from './ReactWorkTags';
import {DidCapture, NoFlags, ShouldCapture} from './ReactFiberFlags';
import {NoMode, ProfileMode} from './ReactTypeOfMode';
-import {
- enableSuspenseServerRenderer,
- enableProfilerTimer,
- enableCache,
-} from 'shared/ReactFeatureFlags';
+import {enableProfilerTimer, enableCache} from 'shared/ReactFeatureFlags';
import {popHostContainer, popHostContext} from './ReactFiberHostContext.new';
import {popSuspenseContext} from './ReactFiberSuspenseContext.new';
@@ -108,20 +104,18 @@ function unwindWork(
}
case SuspenseComponent: {
popSuspenseContext(workInProgress);
- if (enableSuspenseServerRenderer) {
- const suspenseState: null | SuspenseState =
- workInProgress.memoizedState;
- if (suspenseState !== null && suspenseState.dehydrated !== null) {
- if (workInProgress.alternate === null) {
- throw new Error(
- 'Threw in newly mounted dehydrated component. This is likely a bug in ' +
- 'React. Please file an issue.',
- );
- }
-
- resetHydrationState();
+ const suspenseState: null | SuspenseState = workInProgress.memoizedState;
+ if (suspenseState !== null && suspenseState.dehydrated !== null) {
+ if (workInProgress.alternate === null) {
+ throw new Error(
+ 'Threw in newly mounted dehydrated component. This is likely a bug in ' +
+ 'React. Please file an issue.',
+ );
}
+
+ resetHydrationState();
}
+
const flags = workInProgress.flags;
if (flags & ShouldCapture) {
workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;
diff --git a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js
index 1eb4d72d98c98..260b574b264fe 100644
--- a/packages/react-reconciler/src/ReactFiberUnwindWork.old.js
+++ b/packages/react-reconciler/src/ReactFiberUnwindWork.old.js
@@ -28,11 +28,7 @@ import {
} from './ReactWorkTags';
import {DidCapture, NoFlags, ShouldCapture} from './ReactFiberFlags';
import {NoMode, ProfileMode} from './ReactTypeOfMode';
-import {
- enableSuspenseServerRenderer,
- enableProfilerTimer,
- enableCache,
-} from 'shared/ReactFeatureFlags';
+import {enableProfilerTimer, enableCache} from 'shared/ReactFeatureFlags';
import {popHostContainer, popHostContext} from './ReactFiberHostContext.old';
import {popSuspenseContext} from './ReactFiberSuspenseContext.old';
@@ -108,20 +104,18 @@ function unwindWork(
}
case SuspenseComponent: {
popSuspenseContext(workInProgress);
- if (enableSuspenseServerRenderer) {
- const suspenseState: null | SuspenseState =
- workInProgress.memoizedState;
- if (suspenseState !== null && suspenseState.dehydrated !== null) {
- if (workInProgress.alternate === null) {
- throw new Error(
- 'Threw in newly mounted dehydrated component. This is likely a bug in ' +
- 'React. Please file an issue.',
- );
- }
-
- resetHydrationState();
+ const suspenseState: null | SuspenseState = workInProgress.memoizedState;
+ if (suspenseState !== null && suspenseState.dehydrated !== null) {
+ if (workInProgress.alternate === null) {
+ throw new Error(
+ 'Threw in newly mounted dehydrated component. This is likely a bug in ' +
+ 'React. Please file an issue.',
+ );
}
+
+ resetHydrationState();
}
+
const flags = workInProgress.flags;
if (flags & ShouldCapture) {
workInProgress.flags = (flags & ~ShouldCapture) | DidCapture;
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
index e9381e709f226..aa20335cbec91 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.new.js
@@ -23,7 +23,6 @@ import type {
import {
warnAboutDeprecatedLifecycles,
- enableSuspenseServerRenderer,
replayFailedUnitOfWorkWithInvokeGuardedCallback,
enableCreateEventHandleAPI,
enableProfilerTimer,
@@ -2776,26 +2775,22 @@ export function retryDehydratedSuspenseBoundary(boundaryFiber: Fiber) {
export function resolveRetryWakeable(boundaryFiber: Fiber, wakeable: Wakeable) {
let retryLane = NoLane; // Default
let retryCache: WeakSet | Set | null;
- if (enableSuspenseServerRenderer) {
- switch (boundaryFiber.tag) {
- case SuspenseComponent:
- retryCache = boundaryFiber.stateNode;
- const suspenseState: null | SuspenseState = boundaryFiber.memoizedState;
- if (suspenseState !== null) {
- retryLane = suspenseState.retryLane;
- }
- break;
- case SuspenseListComponent:
- retryCache = boundaryFiber.stateNode;
- break;
- default:
- throw new Error(
- 'Pinged unknown suspense boundary type. ' +
- 'This is probably a bug in React.',
- );
- }
- } else {
- retryCache = boundaryFiber.stateNode;
+ switch (boundaryFiber.tag) {
+ case SuspenseComponent:
+ retryCache = boundaryFiber.stateNode;
+ const suspenseState: null | SuspenseState = boundaryFiber.memoizedState;
+ if (suspenseState !== null) {
+ retryLane = suspenseState.retryLane;
+ }
+ break;
+ case SuspenseListComponent:
+ retryCache = boundaryFiber.stateNode;
+ break;
+ default:
+ throw new Error(
+ 'Pinged unknown suspense boundary type. ' +
+ 'This is probably a bug in React.',
+ );
}
if (retryCache !== null) {
diff --git a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
index 5d25610f5f4a8..e2c3a76c7fc24 100644
--- a/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
+++ b/packages/react-reconciler/src/ReactFiberWorkLoop.old.js
@@ -23,7 +23,6 @@ import type {
import {
warnAboutDeprecatedLifecycles,
- enableSuspenseServerRenderer,
replayFailedUnitOfWorkWithInvokeGuardedCallback,
enableCreateEventHandleAPI,
enableProfilerTimer,
@@ -2776,26 +2775,22 @@ export function retryDehydratedSuspenseBoundary(boundaryFiber: Fiber) {
export function resolveRetryWakeable(boundaryFiber: Fiber, wakeable: Wakeable) {
let retryLane = NoLane; // Default
let retryCache: WeakSet | Set | null;
- if (enableSuspenseServerRenderer) {
- switch (boundaryFiber.tag) {
- case SuspenseComponent:
- retryCache = boundaryFiber.stateNode;
- const suspenseState: null | SuspenseState = boundaryFiber.memoizedState;
- if (suspenseState !== null) {
- retryLane = suspenseState.retryLane;
- }
- break;
- case SuspenseListComponent:
- retryCache = boundaryFiber.stateNode;
- break;
- default:
- throw new Error(
- 'Pinged unknown suspense boundary type. ' +
- 'This is probably a bug in React.',
- );
- }
- } else {
- retryCache = boundaryFiber.stateNode;
+ switch (boundaryFiber.tag) {
+ case SuspenseComponent:
+ retryCache = boundaryFiber.stateNode;
+ const suspenseState: null | SuspenseState = boundaryFiber.memoizedState;
+ if (suspenseState !== null) {
+ retryLane = suspenseState.retryLane;
+ }
+ break;
+ case SuspenseListComponent:
+ retryCache = boundaryFiber.stateNode;
+ break;
+ default:
+ throw new Error(
+ 'Pinged unknown suspense boundary type. ' +
+ 'This is probably a bug in React.',
+ );
}
if (retryCache !== null) {
diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js
index aafe4c74d0440..db7babeba5cb2 100644
--- a/packages/shared/ReactFeatureFlags.js
+++ b/packages/shared/ReactFeatureFlags.js
@@ -13,7 +13,6 @@
// Flags that can likely be deleted or landed without consequences
// -----------------------------------------------------------------------------
-export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = true;
export const warnAboutDeprecatedLifecycles = true;
export const enableLazyElements = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js
index f2ce77374235e..5511736bef6db 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-fb.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js
@@ -26,7 +26,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = __PROFILE__;
-export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableLazyElements = false;
export const enableCache = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js
index 43855df94f90d..1ec8cb257c1bc 100644
--- a/packages/shared/forks/ReactFeatureFlags.native-oss.js
+++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js
@@ -20,7 +20,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = __PROFILE__;
-export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableLazyElements = false;
export const enableCache = false;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
index 4283aa16e1201..bbca9a6b371dc 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js
@@ -20,7 +20,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = false;
-export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableLazyElements = false;
export const enableCache = __EXPERIMENTAL__;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
index 938b4d136d73d..49528df4e505f 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
@@ -20,7 +20,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = false;
-export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableLazyElements = false;
export const enableCache = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
index 7ad5cc56d9d92..04a08d5d7418a 100644
--- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
@@ -20,7 +20,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = false;
-export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableLazyElements = false;
export const enableCache = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.testing.js b/packages/shared/forks/ReactFeatureFlags.testing.js
index 0f65c001e5402..dc5bd97016ffa 100644
--- a/packages/shared/forks/ReactFeatureFlags.testing.js
+++ b/packages/shared/forks/ReactFeatureFlags.testing.js
@@ -20,7 +20,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = false;
-export const enableSuspenseServerRenderer = false;
export const enableSelectiveHydration = false;
export const enableLazyElements = false;
export const enableCache = __EXPERIMENTAL__;
diff --git a/packages/shared/forks/ReactFeatureFlags.testing.www.js b/packages/shared/forks/ReactFeatureFlags.testing.www.js
index 93d9860413db8..77250c1251aa8 100644
--- a/packages/shared/forks/ReactFeatureFlags.testing.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.testing.www.js
@@ -20,7 +20,6 @@ export const enableProfilerCommitHooks = false;
export const enableProfilerNestedUpdatePhase = false;
export const enableProfilerNestedUpdateScheduledHook = false;
export const enableUpdaterTracking = false;
-export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = true;
export const enableLazyElements = false;
export const enableCache = true;
diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js
index a108f7a144b9e..db790769ddf65 100644
--- a/packages/shared/forks/ReactFeatureFlags.www.js
+++ b/packages/shared/forks/ReactFeatureFlags.www.js
@@ -67,7 +67,6 @@ export const disableLegacyContext = __EXPERIMENTAL__;
export const warnAboutStringRefs = false;
export const warnAboutDefaultPropsOnFunctionComponents = false;
export const enableGetInspectorDataForInstanceInProduction = false;
-export const enableSuspenseServerRenderer = true;
export const enableSelectiveHydration = true;
export const enableLazyElements = true;