While working with Next.js, one of the most common errors you can encounter is hydration failed error. I'm going to explain why this error occurs and how to fix it.
What is The Reason #
This error is caused by one of the React's apis called hydrateRoot
. This api is used to attach React to the pre-rendered HTML usually generated by the server (react-dom/server) for adding interactivity to (in most cases). The reason why you see it in a Next.js compiled react app is lying here. Since Next.js renders components on server side (SSR), it uses hydrateRoot
api under the hood. When a user visits your site Next.js or other frameworks such as Gatsby or Astro (frameworks that allows server side rendering) serve the user with a statically generated html page. Then, hydrateRoot
api attaches all of the effects, state and/or event listeners to this page. While hydrating React expects this rendered content to be same with the server-rendered content and if it sees any inconsistency between the client and server rendered html during this process, hydration failed error is thrown.
Possible Scenarios Causing Hydration Failed Error #
With this idea on mind, here are some of the reasons why this error can occur in real life scenarios.
- If you nested your html tags incorrectly. For example; if you nested an
<a></a>
tag inside of a<span></span>
tag. While client side rendering can work with improper nesting of html tags because DOM api do allow you to create these tags manually, it is impossible for you to nest html tags in a server side rendered html page. DOM api won't simply parse it. It is good to conclude here that some of the common component libraries such as Material Ui and Ant Desgin have improper nested html components therefore these components may be the reason you are getting this error. - If you try to use browser-based apis such as
localStorage
,sessionStorage
orwindow
in your rendering logic. It may cause the problem because your SSR HTML will not have any access to browser apis on initial render. - A library that is trying to do the above under the hood.
- Client side logic in the render phase. In my latest project it was my
ThemeSwitcher
component that is trying to mutate render logic with a client side state.
I can hear you saying this component has "use client"
so it is rendered client side. You are right. However, even though this component is rendered on the client side, Next.js still hydrates it on the server side.
How to Solve It #
1. You can basically suppress the error.
This solves your problem if you want to cut corners and mutate this error.
2. Using useEffect
Hook
Make sure that the component renders the same content bot on server-side rendering and initial client-side rendering phases. By doing so, you can prevent a hydration mismatch. To do it I created a HydrateWrapper component which returns loader on first render, so the client and server match to prevent hydration error caused by ui updates.
Then wrap your components with This component.
3. You can simply disable SSR on specific components
Summary #
While Next.js and other react frameworks such as Gatsby and Astro try to hydrate server side rendered static pages using hydrateRoot
it may throw hydration warning. When the initial ui doesn't match what was rendered on the server, in other words initial ssr html is different from initial react render logic it throws error. You can easily suppress it, overcome it with useEffect
or disable SSR. If you have any idea, faced this issue or have feedback on my article please leave a comment below. Thanks for reading.