diff --git a/packages/react-art/src/ReactART.js b/packages/react-art/src/ReactART.js
index 9d1b6a16c2038..44cdf4f240a21 100644
--- a/packages/react-art/src/ReactART.js
+++ b/packages/react-art/src/ReactART.js
@@ -69,7 +69,6 @@ class Surface extends React.Component {
this._mountNode = createContainer(
this._surface,
LegacyRoot,
- false,
null,
false,
false,
diff --git a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
index df693b8784992..9d6a38188376d 100644
--- a/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
+++ b/packages/react-dom/src/__tests__/ReactDOMRoot-test.js
@@ -253,6 +253,15 @@ describe('ReactDOMRoot', () => {
);
});
+ it('callback passed to legacy hydrate() API', () => {
+ container.innerHTML = '
Hi
';
+ ReactDOM.hydrate(Hi
, container, () => {
+ Scheduler.unstable_yieldValue('callback');
+ });
+ expect(container.textContent).toEqual('Hi');
+ expect(Scheduler).toHaveYielded(['callback']);
+ });
+
it('warns when unmounting with legacy API (no previous content)', () => {
const root = ReactDOMClient.createRoot(container);
root.render(Hi
);
diff --git a/packages/react-dom/src/client/ReactDOMLegacy.js b/packages/react-dom/src/client/ReactDOMLegacy.js
index 3b751405a3034..af0e35e128bd4 100644
--- a/packages/react-dom/src/client/ReactDOMLegacy.js
+++ b/packages/react-dom/src/client/ReactDOMLegacy.js
@@ -27,6 +27,7 @@ import {
import {
createContainer,
+ createHydrationContainer,
findHostInstanceWithNoPortals,
updateContainer,
flushSync,
@@ -109,34 +110,81 @@ function noopOnRecoverableError() {
function legacyCreateRootFromDOMContainer(
container: Container,
- forceHydrate: boolean,
+ initialChildren: ReactNodeList,
+ parentComponent: ?React$Component,
+ callback: ?Function,
+ isHydrationContainer: boolean,
): FiberRoot {
- // First clear any existing content.
- if (!forceHydrate) {
+ if (isHydrationContainer) {
+ if (typeof callback === 'function') {
+ const originalCallback = callback;
+ callback = function() {
+ const instance = getPublicRootInstance(root);
+ originalCallback.call(instance);
+ };
+ }
+
+ const root = createHydrationContainer(
+ initialChildren,
+ callback,
+ container,
+ LegacyRoot,
+ null, // hydrationCallbacks
+ false, // isStrictMode
+ false, // concurrentUpdatesByDefaultOverride,
+ '', // identifierPrefix
+ noopOnRecoverableError,
+ // TODO(luna) Support hydration later
+ null,
+ );
+ container._reactRootContainer = root;
+ markContainerAsRoot(root.current, container);
+
+ const rootContainerElement =
+ container.nodeType === COMMENT_NODE ? container.parentNode : container;
+ listenToAllSupportedEvents(rootContainerElement);
+
+ flushSync();
+ return root;
+ } else {
+ // First clear any existing content.
let rootSibling;
while ((rootSibling = container.lastChild)) {
container.removeChild(rootSibling);
}
- }
- const root = createContainer(
- container,
- LegacyRoot,
- forceHydrate,
- null, // hydrationCallbacks
- false, // isStrictMode
- false, // concurrentUpdatesByDefaultOverride,
- '', // identifierPrefix
- noopOnRecoverableError, // onRecoverableError
- null, // transitionCallbacks
- );
- markContainerAsRoot(root.current, container);
+ if (typeof callback === 'function') {
+ const originalCallback = callback;
+ callback = function() {
+ const instance = getPublicRootInstance(root);
+ originalCallback.call(instance);
+ };
+ }
+
+ const root = createContainer(
+ container,
+ LegacyRoot,
+ null, // hydrationCallbacks
+ false, // isStrictMode
+ false, // concurrentUpdatesByDefaultOverride,
+ '', // identifierPrefix
+ noopOnRecoverableError, // onRecoverableError
+ null, // transitionCallbacks
+ );
+ container._reactRootContainer = root;
+ markContainerAsRoot(root.current, container);
+
+ const rootContainerElement =
+ container.nodeType === COMMENT_NODE ? container.parentNode : container;
+ listenToAllSupportedEvents(rootContainerElement);
- const rootContainerElement =
- container.nodeType === COMMENT_NODE ? container.parentNode : container;
- listenToAllSupportedEvents(rootContainerElement);
+ // Initial mount should not be batched.
+ flushSync(() => {
+ updateContainer(initialChildren, root, parentComponent, callback);
+ });
- return root;
+ return root;
+ }
}
function warnOnInvalidCallback(callback: mixed, callerName: string): void {
@@ -164,39 +212,30 @@ function legacyRenderSubtreeIntoContainer(
warnOnInvalidCallback(callback === undefined ? null : callback, 'render');
}
- let root = container._reactRootContainer;
- let fiberRoot: FiberRoot;
- if (!root) {
+ const maybeRoot = container._reactRootContainer;
+ let root: FiberRoot;
+ if (!maybeRoot) {
// Initial mount
- root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
+ root = legacyCreateRootFromDOMContainer(
container,
+ children,
+ parentComponent,
+ callback,
forceHydrate,
);
- fiberRoot = root;
- if (typeof callback === 'function') {
- const originalCallback = callback;
- callback = function() {
- const instance = getPublicRootInstance(fiberRoot);
- originalCallback.call(instance);
- };
- }
- // Initial mount should not be batched.
- flushSync(() => {
- updateContainer(children, fiberRoot, parentComponent, callback);
- });
} else {
- fiberRoot = root;
+ root = maybeRoot;
if (typeof callback === 'function') {
const originalCallback = callback;
callback = function() {
- const instance = getPublicRootInstance(fiberRoot);
+ const instance = getPublicRootInstance(root);
originalCallback.call(instance);
};
}
// Update
- updateContainer(children, fiberRoot, parentComponent, callback);
+ updateContainer(children, root, parentComponent, callback);
}
- return getPublicRootInstance(fiberRoot);
+ return getPublicRootInstance(root);
}
export function findDOMNode(
diff --git a/packages/react-dom/src/client/ReactDOMRoot.js b/packages/react-dom/src/client/ReactDOMRoot.js
index d71de3bb0c26d..6e7192ae10453 100644
--- a/packages/react-dom/src/client/ReactDOMRoot.js
+++ b/packages/react-dom/src/client/ReactDOMRoot.js
@@ -225,7 +225,6 @@ export function createRoot(
const root = createContainer(
container,
ConcurrentRoot,
- false,
null,
isStrictMode,
concurrentUpdatesByDefaultOverride,
@@ -302,6 +301,7 @@ export function hydrateRoot(
const root = createHydrationContainer(
initialChildren,
+ null,
container,
ConcurrentRoot,
hydrationCallbacks,
diff --git a/packages/react-native-renderer/src/ReactFabric.js b/packages/react-native-renderer/src/ReactFabric.js
index 127b20fd5dacf..e08a98653fb6c 100644
--- a/packages/react-native-renderer/src/ReactFabric.js
+++ b/packages/react-native-renderer/src/ReactFabric.js
@@ -215,7 +215,6 @@ function render(
root = createContainer(
containerTag,
concurrentRoot ? ConcurrentRoot : LegacyRoot,
- false,
null,
false,
null,
diff --git a/packages/react-native-renderer/src/ReactNativeRenderer.js b/packages/react-native-renderer/src/ReactNativeRenderer.js
index 1dca2cd7a1d93..e751195dda00a 100644
--- a/packages/react-native-renderer/src/ReactNativeRenderer.js
+++ b/packages/react-native-renderer/src/ReactNativeRenderer.js
@@ -211,7 +211,6 @@ function render(
root = createContainer(
containerTag,
LegacyRoot,
- false,
null,
false,
null,
diff --git a/packages/react-noop-renderer/src/createReactNoop.js b/packages/react-noop-renderer/src/createReactNoop.js
index e0ba72076a1af..8e4050dcfa336 100644
--- a/packages/react-noop-renderer/src/createReactNoop.js
+++ b/packages/react-noop-renderer/src/createReactNoop.js
@@ -974,7 +974,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
root = NoopRenderer.createContainer(
container,
tag,
- false,
null,
null,
false,
@@ -996,7 +995,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
const fiberRoot = NoopRenderer.createContainer(
container,
ConcurrentRoot,
- false,
null,
null,
false,
@@ -1029,7 +1027,6 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
const fiberRoot = NoopRenderer.createContainer(
container,
LegacyRoot,
- false,
null,
null,
false,
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.new.js b/packages/react-reconciler/src/ReactFiberReconciler.new.js
index 8607b227e9b40..67eb7f7b232e5 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.new.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.new.js
@@ -245,9 +245,6 @@ function findHostInstanceWithWarning(
export function createContainer(
containerInfo: Container,
tag: RootTag,
- // TODO: We can remove hydration-specific stuff from createContainer once
- // we delete legacy mode. The new root API uses createHydrationContainer.
- hydrate: boolean,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
isStrictMode: boolean,
concurrentUpdatesByDefaultOverride: null | boolean,
@@ -255,6 +252,7 @@ export function createContainer(
onRecoverableError: (error: mixed) => void,
transitionCallbacks: null | TransitionTracingCallbacks,
): OpaqueRoot {
+ const hydrate = false;
return createFiberRoot(
containerInfo,
tag,
@@ -270,6 +268,8 @@ export function createContainer(
export function createHydrationContainer(
initialChildren: ReactNodeList,
+ // TODO: Remove `callback` when we delete legacy mode.
+ callback: ?Function,
containerInfo: Container,
tag: RootTag,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
@@ -305,6 +305,8 @@ export function createHydrationContainer(
// Caution: React DevTools currently depends on this property
// being called "element".
update.payload = {element: initialChildren};
+ update.callback =
+ callback !== undefined && callback !== null ? callback : null;
enqueueUpdate(current, update, lane);
scheduleInitialHydrationOnRoot(root, lane, eventTime);
diff --git a/packages/react-reconciler/src/ReactFiberReconciler.old.js b/packages/react-reconciler/src/ReactFiberReconciler.old.js
index 4970b685b1c1a..378035e95e661 100644
--- a/packages/react-reconciler/src/ReactFiberReconciler.old.js
+++ b/packages/react-reconciler/src/ReactFiberReconciler.old.js
@@ -245,9 +245,6 @@ function findHostInstanceWithWarning(
export function createContainer(
containerInfo: Container,
tag: RootTag,
- // TODO: We can remove hydration-specific stuff from createContainer once
- // we delete legacy mode. The new root API uses createHydrationContainer.
- hydrate: boolean,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
isStrictMode: boolean,
concurrentUpdatesByDefaultOverride: null | boolean,
@@ -255,6 +252,7 @@ export function createContainer(
onRecoverableError: (error: mixed) => void,
transitionCallbacks: null | TransitionTracingCallbacks,
): OpaqueRoot {
+ const hydrate = false;
return createFiberRoot(
containerInfo,
tag,
@@ -270,6 +268,8 @@ export function createContainer(
export function createHydrationContainer(
initialChildren: ReactNodeList,
+ // TODO: Remove `callback` when we delete legacy mode.
+ callback: ?Function,
containerInfo: Container,
tag: RootTag,
hydrationCallbacks: null | SuspenseHydrationCallbacks,
@@ -305,6 +305,8 @@ export function createHydrationContainer(
// Caution: React DevTools currently depends on this property
// being called "element".
update.payload = {element: initialChildren};
+ update.callback =
+ callback !== undefined && callback !== null ? callback : null;
enqueueUpdate(current, update, lane);
scheduleInitialHydrationOnRoot(root, lane, eventTime);
diff --git a/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js b/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js
index d0c3d5b236ea4..82e23de9965da 100644
--- a/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js
+++ b/packages/react-reconciler/src/__tests__/ReactFiberHostContext-test.internal.js
@@ -72,7 +72,6 @@ describe('ReactFiberHostContext', () => {
const container = Renderer.createContainer(
/* root: */ null,
ConcurrentRoot,
- false,
null,
false,
'',
@@ -136,7 +135,6 @@ describe('ReactFiberHostContext', () => {
const container = Renderer.createContainer(
rootContext,
ConcurrentRoot,
- false,
null,
false,
'',
diff --git a/packages/react-test-renderer/src/ReactTestRenderer.js b/packages/react-test-renderer/src/ReactTestRenderer.js
index e850086439a67..76911d701de79 100644
--- a/packages/react-test-renderer/src/ReactTestRenderer.js
+++ b/packages/react-test-renderer/src/ReactTestRenderer.js
@@ -473,7 +473,6 @@ function create(element: React$Element, options: TestRendererOptions) {
let root: FiberRoot | null = createContainer(
container,
isConcurrent ? ConcurrentRoot : LegacyRoot,
- false,
null,
isStrictMode,
concurrentUpdatesByDefault,