This comes with an important caveat though: HTML is inert. Since it is rendered on the server, it cannot tap into browser events (buttons can't handle onClick, forms aren't connected to state and so on).
To address this caveat, we use hydration.
What is hydration?
"React's process of attaching event handlers to the DOM to make server-rendered static HTML interactive. During hydration, React reconciles the server-rendered markup with the client-side JavaScript." - Next.js Glossary
Effectively, the idea is that we can make the page render instantly and at the same time maintain client side interactivity by rendering the static shell of the page first and then adding the client side features.
Why is it called hydration?
The commonly used analogy is of a sponge that is initially dry and is then soaked in water.
How does hydration work under the hood?
Server phase: React executes components on the server using methods like:
Parsing phase: The browser parses the HTML and renders the visual layout immediately.
Download phase: The browser fetches the JavaScript bundle containing React and your component code.
Reconciliation and attachment phase: React executes in the browser, builds an in-memory Virtual DOM tree, matches (reconciles) those nodes with the real DOM nodes already on screen, and binds all event handlers without re-rendering the actual HTML elements.
What are hydration mismatch errors?
"While rendering your application, there was a difference between the React tree that was prerendered from the server and the React tree that was rendered during the first render in the browser (hydration)." - Next.js Hydration Errors
To put it simply, a hydration mismatch error is a discrepancy between the HTML that was pre-rendered on the server and what React computed on the client.
What causes hydration mismatch errors (common triggers)?
Dynamic Data: Rendering new Date() or Math.random() during render, which produces different values on server vs. client.
Invalid HTML Nesting: Browser auto-correcting illegal markup (e.g., placing a <div> inside a <p> tag), causing the client DOM to differ from the server HTML string.
How do you fix hydration mismatch errors (common fixes)?
Resolving hydration mismatch errors comes down to one core principle - ensure the initial client render produces the exact same HTML structure and text that was rendered on the server.
Browsers will autocorrect invalid HTML nesting before hydration.
For instance, if you nest a <div> inside a <p>, the browser automatically splits the <p> into two separate elements in the DOM tree, throwing off React's reconciliation.
// ❌ Invalid HTML: <p> cannot contain block elements like <div>
<p>
<div>Some content</div>
</p>
Use valid HTML structure instead:
// ✅ Valid HTML
<div>
<div>Some content</div>
</div>
Disable SSR for specific components.
Sometimes a component will rely heavily on browser-only functionality.
In this case, you can disable SSR for that particular component which can resolve a hydration mismatch error.
When text or attributes are unavoidably different between the server and the client, you can use suppressHydrationWarning to prevent the error from showing for that specific component.
// Silence warnings on elements with intentionally dynamic text
<span suppressHydrationWarning>
{newDate().toLocaleTimeString()}
</span>
Proceed with caution, though! It does not actually fix the structural mismatch but just silences the error. It should be used sparingly.
Stay in the loop
Get notified when we publish new articles and product updates.
Comments (0)