In React, the UI can be rendered on the client (browser) or the server (Node.js). When HTML is rendered on the server and then made interactive on the client, this process is called hydration.
Understanding hydration vs client rendering is crucial when working with frameworks like Next.js, Remix, or using React’s Server Components.
In CSR, the browser downloads a mostly empty HTML page and runs React on the client to generate and render the UI dynamically.
// Client-side React rendering entry point
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
In SSR, HTML is generated on the server and sent to the client. This improves SEO and first load performance.
// Server-side rendering using Express and ReactDOMServer
import express from "express";
import ReactDOMServer from "react-dom/server";
import App from "./App";
const app = express();
app.get("/", (req, res) => {
const html = ReactDOMServer.renderToString(<App />);
res.send(`<html><body><div id="root">${html}</div></body></html>`);
});
app.listen(3000);
Hydration is the process where React attaches event listeners and internal state logic to server-rendered HTML.
// Hydrating server-rendered HTML on the client
import React from "react";
import { hydrateRoot } from "react-dom/client";
import App from "./App";
hydrateRoot(document.getElementById("root"), <App />);
This simulates the "Uncanny Valley" where content is visible but not yet interactive.
Try clicking "Increment" above. Nothing happens because JS isn't attached.
Goal: Understand how hydration bridges server HTML and client interactivity.