Understand the handoff from server HTML to interactive React.
Read the explanation, run the worked code, then complete the practice lab in Assignments. This advanced lesson includes worked code and a dedicated practice lab.
Understand the idea
Server rendering produces HTML that a browser can display before the application becomes fully interactive. Hydration connects React to that existing markup and its event handlers. In a Vite client-only practice app, createRoot normally creates the UI; in a server-rendered framework, the framework owns the hydration entry point. Do not replace the Edupoly application’s entry point with a manual hydration call.
The server output and the first client render should agree. A timestamp, random value, browser-only storage read or locale-dependent string can differ across environments. Invalid HTML nesting can also make the browser repair the DOM before React hydrates it. Treat hydration warnings as bugs to investigate rather than hiding them with suppressHydrationWarning.
The example begins with a deterministic placeholder and reads the time zone only after mounting. That is appropriate for a small browser-specific enhancement, although it creates an extra render and may cause layout movement. For important data, serialize a consistent server value into the client instead. The distinction between Server Components and Client Components is separate from whether initial HTML was server-rendered; a Client Component in a framework can still contribute to that HTML.
Run the example
Use a separate React practice project with a Node.js version supported by Vite. Create it once with these commands, then use its development URL. Do not paste this into the Edupoly website’s own source files.
npm create vite@latest react-practice -- --template react
cd react-practice
npm install
npm run dev
Replace src/App.jsx with the following complete example. Keep Vite’s generated src/main.jsx entry point.
src/App.jsx
import { useEffect, useState } from 'react';
export default function App() {
const [zone, setZone] = useState(null);
useEffect(() => {setZone(Intl.DateTimeFormat().resolvedOptions().timeZone);}, []);
return <main><h1>Local time zone</h1><p>{zone ?? 'Detecting your time zone…'}</p></main>;
}
Expected result
The initial render is the same deterministic placeholder in every environment; after mounting, the browser’s time-zone name appears. In Vite this demonstrates the two render states, not server hydration itself.
Apply this to your assignments
Run the example in Vite, then inspect the server HTML and hydrated DOM of a separate server-rendered practice project. Compare an initial new Date() value with a serialized timestamp prop. Check invalid nesting and browser-only APIs when diagnosing a mismatch.
Practice starting point
Use the worked example above as your starting point.
Open Assignments for this lesson’s practice lab and acceptance checks.
Common mistakes
Do not use typeof window to choose different initial markup on server and client. Do not access localStorage during a server render. suppressHydrationWarning is not a general repair.
Check your understanding
- Predict the output before running the example, then compare it with the result panel.
- Explain which value each expression reads and which action changes it.
- Try the boundary cases listed in the practice task and record what you observe.
- Rebuild one matching assignment without copying, then compare behavior with the original example.
Reference
Official documentation for this topic · Vite setup requirements
