Skip to content

Commit 8197c73

Browse files
authored
Support document rendering (#24523)
* Support Document as a container for hydration and rendering Previously Document was not handled effectively as a container. in particual when hydrating if there was a fallback to client rendering React would attempt to append a new <html> element into the document before clearing out the existing one which errored leaving the application in brokent state. The initial approach I took was to recycle the documentElement and never remove or append it, always just moving it to the right fiber and appending the right children (heady/body) as needed. However in testing a simple approach in modern browsers it seems like treating the documentElement like any other element works fine. This change modifies the clearContainer method to remove the documentElement if the container is a DOCUMENT_NODE. Once the container is cleared React can append a new documentElement via normal means. * Allow Document as container for createRoot previously rendering into Document was broken and only hydration worked because React did not properly deal with the documentElement and would error in a broken state if used that way. With the previous commit addressing this limitation this change re-adds Document as a valid container for createRoot. It should be noted that if you use document with createRoot it will drop anything a 3rd party scripts adds the page before rendering for the first time.
1 parent d20c3af commit 8197c73

File tree

4 files changed

+5
-6
lines changed

4 files changed

+5
-6
lines changed

packages/react-dom/client.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
} from './';
2424

2525
export function createRoot(
26-
container: Element | DocumentFragment,
26+
container: Element | Document | DocumentFragment,
2727
options?: CreateRootOptions,
2828
): RootType {
2929
if (__DEV__) {

packages/react-dom/src/client/ReactDOM.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ const Internals = {
148148
};
149149

150150
function createRoot(
151-
container: Element | DocumentFragment,
151+
container: Element | Document | DocumentFragment,
152152
options?: CreateRootOptions,
153153
): RootType {
154154
if (__DEV__) {

packages/react-dom/src/client/ReactDOMHostConfig.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -672,9 +672,8 @@ export function clearContainer(container: Container): void {
672672
if (container.nodeType === ELEMENT_NODE) {
673673
((container: any): Element).textContent = '';
674674
} else if (container.nodeType === DOCUMENT_NODE) {
675-
const body = ((container: any): Document).body;
676-
if (body != null) {
677-
body.textContent = '';
675+
if (container.documentElement) {
676+
container.removeChild(container.documentElement);
678677
}
679678
}
680679
}

packages/react-dom/src/client/ReactDOMRoot.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ ReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount = funct
164164
};
165165

166166
export function createRoot(
167-
container: Element | DocumentFragment,
167+
container: Element | Document | DocumentFragment,
168168
options?: CreateRootOptions,
169169
): RootType {
170170
if (!isValidContainer(container)) {

0 commit comments

Comments
 (0)