diff --git a/packages/react-dom-bindings/src/client/ReactDOMComponent.js b/packages/react-dom-bindings/src/client/ReactDOMComponent.js
index 7071f32b75e48..6067ba010d4f8 100644
--- a/packages/react-dom-bindings/src/client/ReactDOMComponent.js
+++ b/packages/react-dom-bindings/src/client/ReactDOMComponent.js
@@ -330,7 +330,6 @@ function normalizeMarkupForTextOrAttribute(markup: mixed): string {
export function checkForUnmatchedText(
serverText: string,
clientText: string | number | bigint,
- isConcurrentMode: boolean,
shouldWarnDev: boolean,
) {
const normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);
@@ -352,7 +351,7 @@ export function checkForUnmatchedText(
}
}
- if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) {
+ if (enableClientRenderFallbackOnTextMismatch) {
// In concurrent roots, we throw when there's a text mismatch and revert to
// client rendering, up to the nearest Suspense boundary.
throw new Error('Text content does not match server-rendered HTML.');
@@ -2746,7 +2745,6 @@ export function diffHydratedProperties(
domElement: Element,
tag: string,
props: Object,
- isConcurrentMode: boolean,
shouldWarnDev: boolean,
hostContext: HostContext,
): void {
@@ -2865,14 +2863,9 @@ export function diffHydratedProperties(
// $FlowFixMe[unsafe-addition] Flow doesn't want us to use `+` operator with string and bigint
if (domElement.textContent !== '' + children) {
if (props.suppressHydrationWarning !== true) {
- checkForUnmatchedText(
- domElement.textContent,
- children,
- isConcurrentMode,
- shouldWarnDev,
- );
+ checkForUnmatchedText(domElement.textContent, children, shouldWarnDev);
}
- if (!isConcurrentMode || !enableClientRenderFallbackOnTextMismatch) {
+ if (!enableClientRenderFallbackOnTextMismatch) {
// We really should be patching this in the commit phase but since
// this only affects legacy mode hydration which is deprecated anyway
// we can get away with it.
@@ -2941,11 +2934,7 @@ export function diffHydratedProperties(
}
}
-export function diffHydratedText(
- textNode: Text,
- text: string,
- isConcurrentMode: boolean,
-): boolean {
+export function diffHydratedText(textNode: Text, text: string): boolean {
const isDifferent = textNode.nodeValue !== text;
return isDifferent;
}
diff --git a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
index 450038eb70dd9..a06f9c00b610f 100644
--- a/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+++ b/packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
@@ -30,8 +30,6 @@ import type {
import {NotPending} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
import {getCurrentRootHostContainer} from 'react-reconciler/src/ReactFiberHostContext';
import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
-// TODO: Remove this deep import when we delete the legacy root API
-import {ConcurrentMode, NoMode} from 'react-reconciler/src/ReactTypeOfMode';
import hasOwnProperty from 'shared/hasOwnProperty';
import {checkAttributeStringCoercion} from 'shared/CheckStringCoercion';
@@ -1370,19 +1368,7 @@ export function hydrateInstance(
// get attached.
updateFiberProps(instance, props);
- // TODO: Temporary hack to check if we're in a concurrent root. We can delete
- // when the legacy root API is removed.
- const isConcurrentMode =
- ((internalInstanceHandle: Fiber).mode & ConcurrentMode) !== NoMode;
-
- diffHydratedProperties(
- instance,
- type,
- props,
- isConcurrentMode,
- shouldWarnDev,
- hostContext,
- );
+ diffHydratedProperties(instance, type, props, shouldWarnDev, hostContext);
}
export function validateHydratableTextInstance(
@@ -1407,12 +1393,7 @@ export function hydrateTextInstance(
): boolean {
precacheFiberNode(internalInstanceHandle, textInstance);
- // TODO: Temporary hack to check if we're in a concurrent root. We can delete
- // when the legacy root API is removed.
- const isConcurrentMode =
- ((internalInstanceHandle: Fiber).mode & ConcurrentMode) !== NoMode;
-
- return diffHydratedText(textInstance, text, isConcurrentMode);
+ return diffHydratedText(textInstance, text);
}
export function hydrateSuspenseInstance(
@@ -1508,15 +1489,9 @@ export function didNotMatchHydratedContainerTextInstance(
parentContainer: Container,
textInstance: TextInstance,
text: string,
- isConcurrentMode: boolean,
shouldWarnDev: boolean,
) {
- checkForUnmatchedText(
- textInstance.nodeValue,
- text,
- isConcurrentMode,
- shouldWarnDev,
- );
+ checkForUnmatchedText(textInstance.nodeValue, text, shouldWarnDev);
}
export function didNotMatchHydratedTextInstance(
@@ -1525,16 +1500,10 @@ export function didNotMatchHydratedTextInstance(
parentInstance: Instance,
textInstance: TextInstance,
text: string,
- isConcurrentMode: boolean,
shouldWarnDev: boolean,
) {
if (parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- checkForUnmatchedText(
- textInstance.nodeValue,
- text,
- isConcurrentMode,
- shouldWarnDev,
- );
+ checkForUnmatchedText(textInstance.nodeValue, text, shouldWarnDev);
}
}
@@ -1577,17 +1546,14 @@ export function didNotHydrateInstance(
parentProps: Props,
parentInstance: Instance,
instance: HydratableInstance,
- isConcurrentMode: boolean,
) {
if (__DEV__) {
- if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- if (instance.nodeType === ELEMENT_NODE) {
- warnForDeletedHydratableElement(parentInstance, (instance: any));
- } else if (instance.nodeType === COMMENT_NODE) {
- // TODO: warnForDeletedHydratableSuspenseBoundary
- } else {
- warnForDeletedHydratableText(parentInstance, (instance: any));
- }
+ if (instance.nodeType === ELEMENT_NODE) {
+ warnForDeletedHydratableElement(parentInstance, (instance: any));
+ } else if (instance.nodeType === COMMENT_NODE) {
+ // TODO: warnForDeletedHydratableSuspenseBoundary
+ } else {
+ warnForDeletedHydratableText(parentInstance, (instance: any));
}
}
}
@@ -1658,12 +1624,9 @@ export function didNotFindHydratableInstance(
parentInstance: Instance,
type: string,
props: Props,
- isConcurrentMode: boolean,
) {
if (__DEV__) {
- if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- warnForInsertedHydratedElement(parentInstance, type, props);
- }
+ warnForInsertedHydratedElement(parentInstance, type, props);
}
}
@@ -1672,12 +1635,9 @@ export function didNotFindHydratableTextInstance(
parentProps: Props,
parentInstance: Instance,
text: string,
- isConcurrentMode: boolean,
) {
if (__DEV__) {
- if (isConcurrentMode || parentProps[SUPPRESS_HYDRATION_WARNING] !== true) {
- warnForInsertedHydratedText(parentInstance, text);
- }
+ warnForInsertedHydratedText(parentInstance, text);
}
}
diff --git a/packages/react-dom/index.classic.fb.js b/packages/react-dom/index.classic.fb.js
index d8814243b690d..b5e974f2b5f25 100644
--- a/packages/react-dom/index.classic.fb.js
+++ b/packages/react-dom/index.classic.fb.js
@@ -24,7 +24,6 @@ export {
hydrateRoot,
findDOMNode,
flushSync,
- hydrate,
render,
unmountComponentAtNode,
unstable_batchedUpdates,
diff --git a/packages/react-dom/index.js b/packages/react-dom/index.js
index 4db349ea5bf0d..0c55c3a92219a 100644
--- a/packages/react-dom/index.js
+++ b/packages/react-dom/index.js
@@ -16,7 +16,6 @@ export {
hydrateRoot,
findDOMNode,
flushSync,
- hydrate,
render,
unmountComponentAtNode,
unstable_batchedUpdates,
diff --git a/packages/react-dom/index.stable.js b/packages/react-dom/index.stable.js
index 36f5563fda5da..5e5a5fe275d95 100644
--- a/packages/react-dom/index.stable.js
+++ b/packages/react-dom/index.stable.js
@@ -14,7 +14,6 @@ export {
hydrateRoot,
findDOMNode,
flushSync,
- hydrate,
render,
unmountComponentAtNode,
unstable_batchedUpdates,
diff --git a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js
index 3eae27486a097..a58f7f8529f98 100644
--- a/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMServerIntegrationReconnecting-test.js
@@ -12,7 +12,6 @@
const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegrationTestUtils');
let React;
-let ReactDOM;
let ReactDOMClient;
let ReactDOMServer;
@@ -453,75 +452,3 @@ describe('ReactDOMServerIntegration', () => {
));
});
});
-
-describe('ReactDOMServerIntegration (legacy)', () => {
- function initModules() {
- // Reset warning cache.
- jest.resetModules();
-
- React = require('react');
- ReactDOM = require('react-dom');
- ReactDOMServer = require('react-dom/server');
-
- // Make them available to the helpers.
- return {
- ReactDOM,
- ReactDOMServer,
- };
- }
-
- const {resetModules, expectMarkupMatch} =
- ReactDOMServerIntegrationUtils(initModules);
-
- beforeEach(() => {
- resetModules();
- });
-
- // @gate !disableLegacyMode
- it('legacy mode can explicitly ignore errors reconnecting different element types of children', () =>
- expectMarkupMatch(
-
,
-
-
-
,
- ));
-
- // @gate !disableLegacyMode
- it('legacy mode can explicitly ignore reconnecting more children', () =>
- expectMarkupMatch(
- ,
- ,
- ));
-
- // @gate !disableLegacyMode
- it('legacy mode can explicitly ignore reconnecting fewer children', () =>
- expectMarkupMatch(
- ,
- ,
- ));
-
- // @gate !disableLegacyMode
- it('legacy mode can explicitly ignore reconnecting reordered children', () =>
- expectMarkupMatch(
- ,
- ,
- ));
-});
diff --git a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js
index 6cdd82fefb011..c8ce39f86e3bf 100644
--- a/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js
+++ b/packages/react-dom/src/__tests__/ReactDOMServerPartialHydration-test.internal.js
@@ -1487,75 +1487,6 @@ describe('ReactDOMServerPartialHydration', () => {
expect(deleted.length).toBe(1);
});
- // @gate !disableLegacyMode
- it('warns and replaces the boundary content in legacy mode', async () => {
- let suspend = false;
- let resolve;
- const promise = new Promise(resolvePromise => (resolve = resolvePromise));
- const ref = React.createRef();
-
- function Child() {
- if (suspend) {
- throw promise;
- } else {
- return 'Hello';
- }
- }
-
- function App() {
- return (
-
-
-
-
-
-
-
- );
- }
-
- // Don't suspend on the server.
- suspend = false;
- const finalHTML = ReactDOMServer.renderToString();
-
- const container = document.createElement('div');
- container.innerHTML = finalHTML;
-
- const span = container.getElementsByTagName('span')[0];
-
- // On the client we try to hydrate.
- suspend = true;
- await expect(async () => {
- await act(() => {
- ReactDOM.hydrate(, container);
- });
- }).toErrorDev(
- 'Warning: Cannot hydrate Suspense in legacy mode. Switch from ' +
- 'ReactDOM.hydrate(element, container) to ' +
- 'ReactDOMClient.hydrateRoot(container, )' +
- '.render(element) or remove the Suspense components from the server ' +
- 'rendered components.' +
- '\n in Suspense (at **)' +
- '\n in div (at **)' +
- '\n in App (at **)',
- );
-
- // We're now in loading state.
- expect(container.textContent).toBe('Loading...');
-
- const span2 = container.getElementsByTagName('span')[0];
- // This is a new node.
- expect(span).not.toBe(span2);
- expect(ref.current).toBe(null);
-
- // Resolving the promise should render the final content.
- suspend = false;
- await act(() => resolve());
-
- // We should now have hydrated with a ref on the existing span.
- expect(container.textContent).toBe('Hello');
- });
-
it('can insert siblings before the dehydrated boundary', async () => {
let suspend = false;
const promise = new Promise(() => {});
diff --git a/packages/react-dom/src/__tests__/ReactLegacyMount-test.js b/packages/react-dom/src/__tests__/ReactLegacyMount-test.js
index 52a5458697d48..6835e9a018a8f 100644
--- a/packages/react-dom/src/__tests__/ReactLegacyMount-test.js
+++ b/packages/react-dom/src/__tests__/ReactLegacyMount-test.js
@@ -13,10 +13,7 @@ const {COMMENT_NODE} = require('react-dom-bindings/src/client/HTMLNodeType');
let React;
let ReactDOM;
-let ReactDOMServer;
-let Scheduler;
let ReactDOMClient;
-let assertLog;
let waitForAll;
describe('ReactMount', () => {
@@ -26,11 +23,8 @@ describe('ReactMount', () => {
React = require('react');
ReactDOM = require('react-dom');
ReactDOMClient = require('react-dom/client');
- ReactDOMServer = require('react-dom/server');
- Scheduler = require('scheduler');
const InternalTestUtils = require('internal-test-utils');
- assertLog = InternalTestUtils.assertLog;
waitForAll = InternalTestUtils.waitForAll;
});
@@ -138,25 +132,6 @@ describe('ReactMount', () => {
expect(instance1 === instance2).toBe(true);
});
- // @gate !disableLegacyMode
- it('does not warn if mounting into left padded rendered markup', () => {
- const container = document.createElement('container');
- container.innerHTML = ReactDOMServer.renderToString() + ' ';
-
- // This should probably ideally warn but we ignore extra markup at the root.
- ReactDOM.hydrate(, container);
- });
-
- // @gate !disableLegacyMode
- it('should warn if mounting into right padded rendered markup', () => {
- const container = document.createElement('container');
- container.innerHTML = ' ' + ReactDOMServer.renderToString();
-
- expect(() => ReactDOM.hydrate(, container)).toErrorDev(
- 'Did not expect server HTML to contain the text node " " in .',
- );
- });
-
// @gate !disableLegacyMode
it('should not warn if mounting into non-empty node', () => {
const container = document.createElement('container');
@@ -174,25 +149,6 @@ describe('ReactMount', () => {
ReactDOM.render(, iFrame.contentDocument.body);
});
- // @gate !disableLegacyMode
- it('should account for escaping on a checksum mismatch', () => {
- const div = document.createElement('div');
- const markup = ReactDOMServer.renderToString(
- This markup contains an nbsp entity: server text
,
- );
- div.innerHTML = markup;
-
- expect(() =>
- ReactDOM.hydrate(
- This markup contains an nbsp entity: client text
,
- div,
- ),
- ).toErrorDev(
- 'Server: "This markup contains an nbsp entity: server text" ' +
- 'Client: "This markup contains an nbsp entity: client text"',
- );
- });
-
// @gate !disableLegacyMode
it('should warn if render removes React-rendered children', () => {
const container = document.createElement('container');
@@ -413,17 +369,6 @@ describe('ReactMount', () => {
expect(container.textContent).toEqual('Bye');
});
- // @gate !disableLegacyMode
- it('callback passed to legacy hydrate() API', () => {
- const container = document.createElement('div');
- container.innerHTML = 'Hi
';
- ReactDOM.hydrate(Hi
, container, () => {
- Scheduler.log('callback');
- });
- expect(container.textContent).toEqual('Hi');
- assertLog(['callback']);
- });
-
// @gate !disableLegacyMode
it('warns when unmounting with legacy API (no previous content)', async () => {
const container = document.createElement('div');
diff --git a/packages/react-dom/src/__tests__/ReactLegacyRootWarnings-test.js b/packages/react-dom/src/__tests__/ReactLegacyRootWarnings-test.js
index 35d63da06b48b..1eef3d140e325 100644
--- a/packages/react-dom/src/__tests__/ReactLegacyRootWarnings-test.js
+++ b/packages/react-dom/src/__tests__/ReactLegacyRootWarnings-test.js
@@ -26,19 +26,4 @@ describe('ReactDOMRoot', () => {
);
}
});
-
- // @gate !disableLegacyMode
- test('deprecation warning for ReactDOM.hydrate', () => {
- spyOnDev(console, 'error');
-
- container.innerHTML = 'Hi';
- ReactDOM.hydrate('Hi', container);
- expect(container.textContent).toEqual('Hi');
- if (__DEV__) {
- expect(console.error).toHaveBeenCalledTimes(1);
- expect(console.error.mock.calls[0][0]).toContain(
- 'ReactDOM.hydrate has not been supported since React 18',
- );
- }
- });
});
diff --git a/packages/react-dom/src/__tests__/ReactRenderDocument-test.js b/packages/react-dom/src/__tests__/ReactRenderDocument-test.js
index b7347470a6656..f719be6981f10 100644
--- a/packages/react-dom/src/__tests__/ReactRenderDocument-test.js
+++ b/packages/react-dom/src/__tests__/ReactRenderDocument-test.js
@@ -345,23 +345,5 @@ describe('rendering React components at document', () => {
]);
expect(testDocument.body.innerHTML).toBe('Hello world');
});
-
- // @gate !disableLegacyMode
- it('supports findDOMNode on full-page components in legacy mode', () => {
- const tree = (
-
-
- Hello World
-
- Hello world
-
- );
-
- const markup = ReactDOMServer.renderToString(tree);
- const testDocument = getTestDocument(markup);
- const component = ReactDOM.hydrate(tree, testDocument);
- expect(testDocument.body.innerHTML).toBe('Hello world');
- expect(ReactDOM.findDOMNode(component).tagName).toBe('HTML');
- });
});
});
diff --git a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js
index 3ca77a661594b..e28296348afa7 100644
--- a/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js
+++ b/packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js
@@ -505,74 +505,6 @@ describe('ReactDOMServerHydration', () => {
await act(() => root.render());
});
- // @gate !disableLegacyMode
- it('Suspense + hydration in legacy mode', () => {
- const element = document.createElement('div');
- element.innerHTML = '';
- const div = element.firstChild.firstChild;
- const ref = React.createRef();
- expect(() =>
- ReactDOM.hydrate(
- ,
- element,
- ),
- ).toErrorDev(
- 'Warning: Did not expect server HTML to contain a in
.',
- );
-
- // The content should've been client rendered and replaced the
- // existing div.
- expect(ref.current).not.toBe(div);
- // The HTML should be the same though.
- expect(element.innerHTML).toBe('
');
- });
-
- // @gate !disableLegacyMode
- it('Suspense + hydration in legacy mode (at root)', () => {
- const element = document.createElement('div');
- element.innerHTML = '
Hello World
';
- const div = element.firstChild;
- const ref = React.createRef();
- ReactDOM.hydrate(
-
- Hello World
- ,
- element,
- );
-
- // The content should've been client rendered.
- expect(ref.current).not.toBe(div);
- // Unfortunately, since we don't delete the tail at the root, a duplicate will remain.
- expect(element.innerHTML).toBe(
- '
Hello World
Hello World
',
- );
- });
-
- // @gate !disableLegacyMode
- it('Suspense + hydration in legacy mode with no fallback', () => {
- const element = document.createElement('div');
- element.innerHTML = '
Hello World
';
- const div = element.firstChild;
- const ref = React.createRef();
- ReactDOM.hydrate(
-
- Hello World
- ,
- element,
- );
-
- // The content should've been client rendered.
- expect(ref.current).not.toBe(div);
- // Unfortunately, since we don't delete the tail at the root, a duplicate will remain.
- expect(element.innerHTML).toBe(
- '
Hello World
Hello World
',
- );
- });
-
// regression test for https://github.com/facebook/react/issues/17170
it('should not warn if dangerouslySetInnerHtml=undefined', async () => {
const domElement = document.createElement('div');
diff --git a/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js b/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js
index e9c4479b028fb..015942131d01d 100644
--- a/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js
+++ b/packages/react-dom/src/__tests__/utils/ReactDOMServerIntegrationTestUtils.js
@@ -52,15 +52,11 @@ module.exports = function (initModules) {
async function asyncReactDOMRender(reactElement, domElement, forceHydrate) {
if (forceHydrate) {
await act(() => {
- if (ReactDOMClient) {
- ReactDOMClient.hydrateRoot(domElement, reactElement, {
- onRecoverableError: () => {
- // TODO: assert on recoverable error count.
- },
- });
- } else {
- ReactDOM.hydrate(reactElement, domElement);
- }
+ ReactDOMClient.hydrateRoot(domElement, reactElement, {
+ onRecoverableError: () => {
+ // TODO: assert on recoverable error count.
+ },
+ });
});
} else {
await act(() => {
diff --git a/packages/react-dom/src/client/ReactDOM.js b/packages/react-dom/src/client/ReactDOM.js
index 78fffeb41cb34..9f9ea849fd66d 100644
--- a/packages/react-dom/src/client/ReactDOM.js
+++ b/packages/react-dom/src/client/ReactDOM.js
@@ -21,7 +21,6 @@ import type {
import {
findDOMNode,
render,
- hydrate,
unstable_renderSubtreeIntoContainer,
unmountComponentAtNode,
} from './ReactDOMLegacy';
@@ -172,7 +171,6 @@ export {
ReactVersion as version,
// Disabled behind disableLegacyReactDOMAPIs
findDOMNode,
- hydrate,
render,
unmountComponentAtNode,
// exposeConcurrentModeAPIs
diff --git a/packages/react-dom/src/client/ReactDOMLegacy.js b/packages/react-dom/src/client/ReactDOMLegacy.js
index 64fef73640b10..50cb6fbf94b10 100644
--- a/packages/react-dom/src/client/ReactDOMLegacy.js
+++ b/packages/react-dom/src/client/ReactDOMLegacy.js
@@ -260,54 +260,6 @@ export function findDOMNode(
return findHostInstance(componentOrElement);
}
-export function hydrate(
- element: React$Node,
- container: Container,
- callback: ?Function,
-): React$Component
| PublicInstance | null {
- if (disableLegacyMode) {
- if (__DEV__) {
- console.error(
- 'ReactDOM.hydrate was removed in React 19. Use hydrateRoot instead',
- );
- }
- throw new Error('ReactDOM: Unsupported Legacy Mode API.');
- }
- if (__DEV__) {
- console.error(
- 'ReactDOM.hydrate has not been supported since React 18. Use hydrateRoot ' +
- 'instead. Until you switch to the new API, your app will behave as ' +
- "if it's running React 17. Learn " +
- 'more: https://react.dev/link/switch-to-createroot',
- );
- }
-
- if (!isValidContainerLegacy(container)) {
- throw new Error('Target container is not a DOM element.');
- }
-
- if (__DEV__) {
- const isModernRoot =
- isContainerMarkedAsRoot(container) &&
- container._reactRootContainer === undefined;
- if (isModernRoot) {
- console.error(
- 'You are calling ReactDOM.hydrate() on a container that was previously ' +
- 'passed to ReactDOMClient.createRoot(). This is not supported. ' +
- 'Did you mean to call hydrateRoot(container, element)?',
- );
- }
- }
- // TODO: throw or warn if we couldn't hydrate?
- return legacyRenderSubtreeIntoContainer(
- null,
- element,
- container,
- true,
- callback,
- );
-}
-
export function render(
element: React$Element,
container: Container,
diff --git a/packages/react-dom/unstable_testing.classic.fb.js b/packages/react-dom/unstable_testing.classic.fb.js
index 6dd68f3669dc3..9958b22cc3277 100644
--- a/packages/react-dom/unstable_testing.classic.fb.js
+++ b/packages/react-dom/unstable_testing.classic.fb.js
@@ -11,7 +11,6 @@ export {
createPortal,
findDOMNode,
flushSync,
- hydrate,
render,
unmountComponentAtNode,
unstable_batchedUpdates,
diff --git a/packages/react-dom/unstable_testing.js b/packages/react-dom/unstable_testing.js
index 9729a427e4aa6..080b7340d11b2 100644
--- a/packages/react-dom/unstable_testing.js
+++ b/packages/react-dom/unstable_testing.js
@@ -11,7 +11,6 @@ export {
createPortal,
findDOMNode,
flushSync,
- hydrate,
render,
unmountComponentAtNode,
unstable_batchedUpdates,
diff --git a/packages/react-dom/unstable_testing.stable.js b/packages/react-dom/unstable_testing.stable.js
index 453e8b4fdece7..855f6f1fc006a 100644
--- a/packages/react-dom/unstable_testing.stable.js
+++ b/packages/react-dom/unstable_testing.stable.js
@@ -11,7 +11,6 @@ export {
createPortal,
findDOMNode,
flushSync,
- hydrate,
render,
unmountComponentAtNode,
unstable_batchedUpdates,
diff --git a/packages/react-reconciler/src/ReactFiber.js b/packages/react-reconciler/src/ReactFiber.js
index 194bababd644d..ce909b802530a 100644
--- a/packages/react-reconciler/src/ReactFiber.js
+++ b/packages/react-reconciler/src/ReactFiber.js
@@ -849,12 +849,6 @@ export function createFiberFromText(
return fiber;
}
-export function createFiberFromHostInstanceForDeletion(): Fiber {
- const fiber = createFiber(HostComponent, null, null, NoMode);
- fiber.elementType = 'DELETED';
- return fiber;
-}
-
export function createFiberFromDehydratedFragment(
dehydratedNode: SuspenseInstance,
): Fiber {
diff --git a/packages/react-reconciler/src/ReactFiberBeginWork.js b/packages/react-reconciler/src/ReactFiberBeginWork.js
index 0b788996bd10b..28e04f7c4b870 100644
--- a/packages/react-reconciler/src/ReactFiberBeginWork.js
+++ b/packages/react-reconciler/src/ReactFiberBeginWork.js
@@ -141,7 +141,6 @@ import {
import {
NoLane,
NoLanes,
- SyncLane,
OffscreenLane,
DefaultHydrationLane,
SomeRetryLane,
@@ -2743,18 +2742,7 @@ function mountDehydratedSuspenseComponent(
): null | Fiber {
// During the first pass, we'll bail out and not drill into the children.
// Instead, we'll leave the content in place and try to hydrate it later.
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- if (__DEV__) {
- console.error(
- 'Cannot hydrate Suspense in legacy mode. Switch from ' +
- 'ReactDOM.hydrate(element, container) to ' +
- 'ReactDOMClient.hydrateRoot(container, )' +
- '.render(element) or remove the Suspense components from ' +
- 'the server rendered components.',
- );
- }
- workInProgress.lanes = laneToLanes(SyncLane);
- } else if (isSuspenseInstanceFallback(suspenseInstance)) {
+ if (isSuspenseInstanceFallback(suspenseInstance)) {
// This is a client-only boundary. Since we won't get any content from the server
// for this, we need to schedule that at a higher priority based on when it would
// have timed out. In theory we could render it in this pass but it would have the
@@ -2794,15 +2782,6 @@ function updateDehydratedSuspenseComponent(
// but after we've already committed once.
warnIfHydrating();
- if ((workInProgress.mode & ConcurrentMode) === NoMode) {
- return retrySuspenseComponentWithoutHydrating(
- current,
- workInProgress,
- renderLanes,
- null,
- );
- }
-
if (isSuspenseInstanceFallback(suspenseInstance)) {
// This boundary is in a permanent fallback state. In this case, we'll never
// get an update and we'll never be able to hydrate the final content. Let's just try the
diff --git a/packages/react-reconciler/src/ReactFiberHydrationContext.js b/packages/react-reconciler/src/ReactFiberHydrationContext.js
index 90d87e13d7b33..11cb591ec9a8b 100644
--- a/packages/react-reconciler/src/ReactFiberHydrationContext.js
+++ b/packages/react-reconciler/src/ReactFiberHydrationContext.js
@@ -8,7 +8,6 @@
*/
import type {Fiber} from './ReactInternalTypes';
-import {NoMode, ConcurrentMode} from './ReactTypeOfMode';
import type {
Instance,
TextInstance,
@@ -28,19 +27,9 @@ import {
HostRoot,
SuspenseComponent,
} from './ReactWorkTags';
-import {
- ChildDeletion,
- Placement,
- Hydrating,
- NoFlags,
- DidCapture,
-} from './ReactFiberFlags';
import {enableClientRenderFallbackOnTextMismatch} from 'shared/ReactFeatureFlags';
-import {
- createFiberFromHostInstanceForDeletion,
- createFiberFromDehydratedFragment,
-} from './ReactFiber';
+import {createFiberFromDehydratedFragment} from './ReactFiber';
import {
shouldSetTextContent,
supportsHydration,
@@ -168,14 +157,11 @@ function warnUnhydratedInstance(
}
case HostSingleton:
case HostComponent: {
- const isConcurrentMode = (returnFiber.mode & ConcurrentMode) !== NoMode;
didNotHydrateInstance(
returnFiber.type,
returnFiber.memoizedProps,
returnFiber.stateNode,
instance,
- // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode,
);
break;
}
@@ -192,23 +178,6 @@ function warnUnhydratedInstance(
}
}
-function deleteHydratableInstance(
- returnFiber: Fiber,
- instance: HydratableInstance,
-) {
- const childToDelete = createFiberFromHostInstanceForDeletion();
- childToDelete.stateNode = instance;
- childToDelete.return = returnFiber;
-
- const deletions = returnFiber.deletions;
- if (deletions === null) {
- returnFiber.deletions = [childToDelete];
- returnFiber.flags |= ChildDeletion;
- } else {
- deletions.push(childToDelete);
- }
-}
-
function warnNonHydratedInstance(returnFiber: Fiber, fiber: Fiber) {
if (__DEV__) {
if (didSuspendOrErrorDEV) {
@@ -257,30 +226,22 @@ function warnNonHydratedInstance(returnFiber: Fiber, fiber: Fiber) {
case HostComponent: {
const type = fiber.type;
const props = fiber.pendingProps;
- const isConcurrentMode =
- (returnFiber.mode & ConcurrentMode) !== NoMode;
didNotFindHydratableInstance(
parentType,
parentProps,
parentInstance,
type,
props,
- // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode,
);
break;
}
case HostText: {
const text = fiber.pendingProps;
- const isConcurrentMode =
- (returnFiber.mode & ConcurrentMode) !== NoMode;
didNotFindHydratableTextInstance(
parentType,
parentProps,
parentInstance,
text,
- // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode,
);
break;
}
@@ -330,9 +291,6 @@ function warnNonHydratedInstance(returnFiber: Fiber, fiber: Fiber) {
}
}
}
-function insertNonHydratedInstance(returnFiber: Fiber, fiber: Fiber) {
- fiber.flags = (fiber.flags & ~Hydrating) | Placement;
-}
function tryHydrateInstance(fiber: Fiber, nextInstance: any) {
// fiber is a HostComponent Fiber
@@ -400,13 +358,6 @@ function tryHydrateSuspense(fiber: Fiber, nextInstance: any) {
return false;
}
-function shouldClientRenderOnMismatch(fiber: Fiber) {
- return (
- (fiber.mode & ConcurrentMode) !== NoMode &&
- (fiber.flags & DidCapture) === NoFlags
- );
-}
-
function throwOnHydrationMismatch(fiber: Fiber) {
throw new Error(
'Hydration failed because the initial UI does not match what was ' +
@@ -447,60 +398,12 @@ function tryToClaimNextHydratableInstance(fiber: Fiber): void {
currentHostContext,
);
- const initialInstance = nextHydratableInstance;
const nextInstance = nextHydratableInstance;
- if (!nextInstance) {
- if (shouldClientRenderOnMismatch(fiber)) {
- if (shouldKeepWarning) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- }
- throwOnHydrationMismatch(fiber);
- }
- // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance((hydrationParentFiber: any), fiber);
+ if (!nextInstance || !tryHydrateInstance(fiber, nextInstance)) {
if (shouldKeepWarning) {
warnNonHydratedInstance((hydrationParentFiber: any), fiber);
}
- isHydrating = false;
- hydrationParentFiber = fiber;
- nextHydratableInstance = initialInstance;
- return;
- }
- const firstAttemptedInstance = nextInstance;
- if (!tryHydrateInstance(fiber, nextInstance)) {
- if (shouldClientRenderOnMismatch(fiber)) {
- if (shouldKeepWarning) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- }
- throwOnHydrationMismatch(fiber);
- }
- // If we can't hydrate this instance let's try the next one.
- // We use this as a heuristic. It's based on intuition and not data so it
- // might be flawed or unnecessary.
- nextHydratableInstance = getNextHydratableSibling(nextInstance);
- const prevHydrationParentFiber: Fiber = (hydrationParentFiber: any);
- if (
- !nextHydratableInstance ||
- !tryHydrateInstance(fiber, nextHydratableInstance)
- ) {
- // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance((hydrationParentFiber: any), fiber);
- if (shouldKeepWarning) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- }
- isHydrating = false;
- hydrationParentFiber = fiber;
- nextHydratableInstance = initialInstance;
- return;
- }
- // We matched the next one, we'll now assume that the first one was
- // superfluous and we'll delete it. Since we can't eagerly delete it
- // we'll have to schedule a deletion. To do that, this node needs a dummy
- // fiber associated with it.
- if (shouldKeepWarning) {
- warnUnhydratedInstance(prevHydrationParentFiber, firstAttemptedInstance);
- }
- deleteHydratableInstance(prevHydrationParentFiber, firstAttemptedInstance);
+ throwOnHydrationMismatch(fiber);
}
}
@@ -515,63 +418,12 @@ function tryToClaimNextHydratableTextInstance(fiber: Fiber): void {
const currentHostContext = getHostContext();
shouldKeepWarning = validateHydratableTextInstance(text, currentHostContext);
- const initialInstance = nextHydratableInstance;
const nextInstance = nextHydratableInstance;
- if (!nextInstance) {
- // We exclude non hydrabable text because we know there are no matching hydratables.
- // We either throw or insert depending on the render mode.
- if (shouldClientRenderOnMismatch(fiber)) {
- if (shouldKeepWarning) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- }
- throwOnHydrationMismatch(fiber);
- }
- // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance((hydrationParentFiber: any), fiber);
+ if (!nextInstance || !tryHydrateText(fiber, nextInstance)) {
if (shouldKeepWarning) {
warnNonHydratedInstance((hydrationParentFiber: any), fiber);
}
- isHydrating = false;
- hydrationParentFiber = fiber;
- nextHydratableInstance = initialInstance;
- return;
- }
- const firstAttemptedInstance = nextInstance;
- if (!tryHydrateText(fiber, nextInstance)) {
- if (shouldClientRenderOnMismatch(fiber)) {
- if (shouldKeepWarning) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- }
- throwOnHydrationMismatch(fiber);
- }
- // If we can't hydrate this instance let's try the next one.
- // We use this as a heuristic. It's based on intuition and not data so it
- // might be flawed or unnecessary.
- nextHydratableInstance = getNextHydratableSibling(nextInstance);
- const prevHydrationParentFiber: Fiber = (hydrationParentFiber: any);
-
- if (
- !nextHydratableInstance ||
- !tryHydrateText(fiber, nextHydratableInstance)
- ) {
- // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance((hydrationParentFiber: any), fiber);
- if (shouldKeepWarning) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- }
- isHydrating = false;
- hydrationParentFiber = fiber;
- nextHydratableInstance = initialInstance;
- return;
- }
- // We matched the next one, we'll now assume that the first one was
- // superfluous and we'll delete it. Since we can't eagerly delete it
- // we'll have to schedule a deletion. To do that, this node needs a dummy
- // fiber associated with it.
- if (shouldKeepWarning) {
- warnUnhydratedInstance(prevHydrationParentFiber, firstAttemptedInstance);
- }
- deleteHydratableInstance(prevHydrationParentFiber, firstAttemptedInstance);
+ throwOnHydrationMismatch(fiber);
}
}
@@ -579,51 +431,10 @@ function tryToClaimNextHydratableSuspenseInstance(fiber: Fiber): void {
if (!isHydrating) {
return;
}
- const initialInstance = nextHydratableInstance;
const nextInstance = nextHydratableInstance;
- if (!nextInstance) {
- if (shouldClientRenderOnMismatch(fiber)) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- throwOnHydrationMismatch(fiber);
- }
- // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance((hydrationParentFiber: any), fiber);
+ if (!nextInstance || !tryHydrateSuspense(fiber, nextInstance)) {
warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- isHydrating = false;
- hydrationParentFiber = fiber;
- nextHydratableInstance = initialInstance;
- return;
- }
- const firstAttemptedInstance = nextInstance;
- if (!tryHydrateSuspense(fiber, nextInstance)) {
- if (shouldClientRenderOnMismatch(fiber)) {
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- throwOnHydrationMismatch(fiber);
- }
- // If we can't hydrate this instance let's try the next one.
- // We use this as a heuristic. It's based on intuition and not data so it
- // might be flawed or unnecessary.
- nextHydratableInstance = getNextHydratableSibling(nextInstance);
- const prevHydrationParentFiber: Fiber = (hydrationParentFiber: any);
-
- if (
- !nextHydratableInstance ||
- !tryHydrateSuspense(fiber, nextHydratableInstance)
- ) {
- // Nothing to hydrate. Make it an insertion.
- insertNonHydratedInstance((hydrationParentFiber: any), fiber);
- warnNonHydratedInstance((hydrationParentFiber: any), fiber);
- isHydrating = false;
- hydrationParentFiber = fiber;
- nextHydratableInstance = initialInstance;
- return;
- }
- // We matched the next one, we'll now assume that the first one was
- // superfluous and we'll delete it. Since we can't eagerly delete it
- // we'll have to schedule a deletion. To do that, this node needs a dummy
- // fiber associated with it.
- warnUnhydratedInstance(prevHydrationParentFiber, firstAttemptedInstance);
- deleteHydratableInstance(prevHydrationParentFiber, firstAttemptedInstance);
+ throwOnHydrationMismatch(fiber);
}
}
@@ -703,17 +514,13 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
switch (returnFiber.tag) {
case HostRoot: {
const parentContainer = returnFiber.stateNode.containerInfo;
- const isConcurrentMode =
- (returnFiber.mode & ConcurrentMode) !== NoMode;
didNotMatchHydratedContainerTextInstance(
parentContainer,
textInstance,
textContent,
- // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode,
shouldWarnIfMismatchDev,
);
- if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) {
+ if (enableClientRenderFallbackOnTextMismatch) {
// In concurrent mode we never update the mismatched text,
// even if the error was ignored.
return false;
@@ -725,19 +532,15 @@ function prepareToHydrateHostTextInstance(fiber: Fiber): boolean {
const parentType = returnFiber.type;
const parentProps = returnFiber.memoizedProps;
const parentInstance = returnFiber.stateNode;
- const isConcurrentMode =
- (returnFiber.mode & ConcurrentMode) !== NoMode;
didNotMatchHydratedTextInstance(
parentType,
parentProps,
parentInstance,
textInstance,
textContent,
- // TODO: Delete this argument when we remove the legacy root API.
- isConcurrentMode,
shouldWarnIfMismatchDev,
);
- if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) {
+ if (enableClientRenderFallbackOnTextMismatch) {
// In concurrent mode we never update the mismatched text,
// even if the error was ignored.
return false;
@@ -861,18 +664,10 @@ function popHydrationState(fiber: Fiber): boolean {
}
}
if (shouldClear) {
- let nextInstance = nextHydratableInstance;
+ const nextInstance = nextHydratableInstance;
if (nextInstance) {
- if (shouldClientRenderOnMismatch(fiber)) {
- warnIfUnhydratedTailNodes(fiber);
- throwOnHydrationMismatch(fiber);
- } else {
- while (nextInstance) {
- warnUnhydratedInstance(fiber, nextInstance);
- deleteHydratableInstance(fiber, nextInstance);
- nextInstance = getNextHydratableSibling(nextInstance);
- }
- }
+ warnIfUnhydratedTailNodes(fiber);
+ throwOnHydrationMismatch(fiber);
}
}
popToNextHostParent(fiber);