When React renders content into a DOM node (like the `root` div), it interacts with any pre-existing HTML in that node. Understanding this behavior is key to managing initial page loads and hydration.
Existing HTML in the root div is displayed until React’s render()
method executes and replaces it with the React component tree. This can serve as a fallback or initial content before React takes over.
<!DOCTYPE html> <html> <head> <title>My App</title> </head> <body> <div id="root"> <h1>Loading...</h1> <p>This is initial HTML content.</p> </div> <script src="app.js"></script> </body> </html> // app.js import React from "react"; import ReactDOM from "react-dom"; const App = React.createElement("div", {}, "React Content Loaded!"); const root = ReactDOM.createRoot(document.getElementById("root")); root.render(<App />);
In this example, "Loading..." and the paragraph appear briefly until React replaces them with "React Content Loaded!".
In server-side rendering (SSR) scenarios, pre-existing HTML isn’t replaced but "hydrated"—React attaches event listeners and makes it interactive without re-rendering the DOM from scratch.
// Server-rendered HTML <div id="root"> <div>Server-rendered content</div> </div> // Client-side hydration import React from "react"; import ReactDOM from "react-dom"; const App = React.createElement("div", {}, "Server-rendered content"); ReactDOM.hydrate(<App />, document.getElementById("root"));
Note: Tools like Next.js handle much of this automatically, optimizing the interplay between static HTML and React rendering.