Suggest an editImprove this articleRefine the answer for “HTML mismatch”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)If, after SSR, the client's virtual DOM **does not exactly match** the HTML the server generated, React logs a hydration-error warning to the console and may **re-render part of the tree**, causing lost state or a flickering interface. **Key point:** the cause is usually non-deterministic rendering - `Math.random()`, `Date.now()`, accessing `window` before hydration, and so on.Shown above the full answer for quick recall.Answer (EN)Image## Context: what hydration is After SSR, the browser receives **ready-made HTML**. The client-side JavaScript (React, Vue, etc.) then **performs the same render** to "attach" logic and events to the already existing DOM. This process is called **hydration**. For hydration to succeed: > The client-side virtual DOM must **exactly match** the HTML the server generated. --- ## What happens on a mismatch ### 1. React tries to "reconcile" the DOM React compares the existing HTML (from the server) with what it **expects** during client-side rendering. If the differences are minor (for example, a `class` attribute or the text inside an element), React may try to **silently fix** the DOM. If the differences are significant, React will log a warning or even re-render part of the tree. --- ### 2. React logs an error to the console You will see a message like: ```javascript Warning: Text content did not match. Server: "42" Client: "43" ``` or ```javascript Warning: Hydration failed because the initial UI does not match what was rendered on the server. ``` This means React expected one tree and got a different one. --- ### 3. Possible consequences | Situation | What happens | |---|---| | **Small differences (text, attribute)** | React silently fixes the DOM, but this can trigger a "reflow" or a flickering interface | | **Significant differences (different structure)** | React removes the old HTML and **re-renders the component from scratch** | | **Widespread mismatches** | Lost state, effects running twice, logic bugs | | **In strict mode (React 18 StrictMode)** | React logs a warning and may reset the whole tree | --- ### Example #### The server returned: ```javascript <div id="root"> <p>Today: October 17</p> </div> ``` #### The client rendered: ```javascript <div id="root"> <p>Today: October 18</p> </div> ``` React detects the mismatch and shows: ```javascript Warning: Text content did not match. Server: "Today: October 17" Client: "Today: October 18" ``` The user sees a brief content "flicker" - React replaces the text after hydration. --- ## Main causes of hydration errors ### 1. Using "unstable" values - `Math.random()` - `Date.now()` - `new Date()` - UUID / random keys - random ids (for example, `id={Math.random()}`) Solution: Generate them **on the server ahead of time** and pass them through props. --- ### 2. Code that depends on the browser The server has no `window`, `document`, `navigator`, `localStorage`, and so on. Wrong: ```javascript const width = window.innerWidth; // Error during SSR ``` Correct: ```javascript const [width, setWidth] = useState(0); useEffect(() => setWidth(window.innerWidth), []); ``` --- ### 3. Conditional rendering that depends on the environment If a component renders differently depending on: - screen size, - the user's session, - locale, - cookie / theme mode. Example: ```javascript {typeof window !== "undefined" && <Sidebar />} ``` The server has no `window` → Sidebar does not render. The client has `window` → Sidebar appears → mismatch. Solution: Render with the same conditions, or use `useEffect` for client-only code. --- ### 4. A difference in data between the server and the client If SSR loads one set of data and the client requests different data again → an HTML mismatch. Solution: - Pass `initialData` from SSR to the client through `__INITIAL_STATE__` or `pageProps`. - Use the same data-loading logic. --- ## How React reacts (React 18+) | Version | Behavior | |---|---| | React 17 and below | Silently fixed the differences (often caused bugs) | | React 18 | Explicitly warns in the console and **may reset the DOM** | | React 18 (StrictMode) | Checks with a double render to catch mismatches | --- ## How to avoid mismatches 1. Use **deterministic data** during SSR. 2. Do not render browser-dependent elements before hydration. 3. Pass all **initial props/data** to the client. 4. Test the SSR render with `ReactDOMServer.renderToString()` locally. 5. Enable `StrictMode` - it helps catch hydration bugs. --- ## Conclusion If the HTML generated on the server **does not match the client's**: - React logs a warning or a hydration error. - A **re-render** may occur, along with lost state or a flickering interface. - This is often caused by **non-deterministic rendering** (dates, randomness, window, and so on). > Ideal SSR hydration means the same HTML, > regardless of whether it was generated on the server or the client.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.