Skip to main content

HTML mismatch

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

SituationWhat 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 mismatchesLost 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+)

VersionBehavior
React 17 and belowSilently fixed the differences (often caused bugs)
React 18Explicitly 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.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.