mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Pass children to hydration root constructor
I already made this change for the concurrent root API in #23309. This does the same thing for the legacy API. Doesn't change any behavior, but I will use this in the next steps.
This commit is contained in:
Vendored
-1
@@ -69,7 +69,6 @@ class Surface extends React.Component {
|
||||
this._mountNode = createContainer(
|
||||
this._surface,
|
||||
LegacyRoot,
|
||||
false,
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
|
||||
@@ -253,6 +253,15 @@ describe('ReactDOMRoot', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('callback passed to legacy hydrate() API', () => {
|
||||
container.innerHTML = '<div>Hi</div>';
|
||||
ReactDOM.hydrate(<div>Hi</div>, 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(<div>Hi</div>);
|
||||
|
||||
+81
-42
@@ -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<any, any>,
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Initial mount should not be batched.
|
||||
flushSync(() => {
|
||||
updateContainer(initialChildren, root, parentComponent, callback);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
const root = createContainer(
|
||||
container,
|
||||
LegacyRoot,
|
||||
forceHydrate,
|
||||
null, // hydrationCallbacks
|
||||
false, // isStrictMode
|
||||
false, // concurrentUpdatesByDefaultOverride,
|
||||
'', // identifierPrefix
|
||||
noopOnRecoverableError, // onRecoverableError
|
||||
null, // transitionCallbacks
|
||||
);
|
||||
markContainerAsRoot(root.current, container);
|
||||
|
||||
const rootContainerElement =
|
||||
container.nodeType === COMMENT_NODE ? container.parentNode : container;
|
||||
listenToAllSupportedEvents(rootContainerElement);
|
||||
|
||||
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(
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
@@ -215,7 +215,6 @@ function render(
|
||||
root = createContainer(
|
||||
containerTag,
|
||||
concurrentRoot ? ConcurrentRoot : LegacyRoot,
|
||||
false,
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
|
||||
@@ -211,7 +211,6 @@ function render(
|
||||
root = createContainer(
|
||||
containerTag,
|
||||
LegacyRoot,
|
||||
false,
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
'',
|
||||
|
||||
@@ -473,7 +473,6 @@ function create(element: React$Element<any>, options: TestRendererOptions) {
|
||||
let root: FiberRoot | null = createContainer(
|
||||
container,
|
||||
isConcurrent ? ConcurrentRoot : LegacyRoot,
|
||||
false,
|
||||
null,
|
||||
isStrictMode,
|
||||
concurrentUpdatesByDefault,
|
||||
|
||||
Reference in New Issue
Block a user