Next.js: Hydration failed because the initial UI does not match
Educational use only. Content explains errors and defensive fixes for systems you own or are authorised to test. Do not use any technique here to access data, accounts, or networks without permission.
Root Cause
This is a notorious issue in Server-Side Rendered (SSR) React frameworks like Next.js. The server generates the initial HTML based on the state at the time of the request. When the browser receives this HTML, React "hydrates" it by attaching event listeners and re-rendering. If the client-side render produces a different DOM structure than the server-side HTML, React throws a hydration mismatch error. The most common cause is using browser-only APIs (like `window.innerWidth` or `localStorage`) during the initial render. Since `window` isn't defined on the server, the server outputs one thing, and the client outputs another.
Fix / Solution
Ensure that the initial render is identical on both the server and client. Defer logic that relies on browser APIs until after hydration by placing it inside a `useEffect` hook, which only runs on the client. Alternatively, if a component fundamentally cannot be rendered on the server, dynamically import it with `ssr: false` in Next.js.
Code Snippet
// ❌ Mismatch: typeof window is 'undefined' on server, but 'object' on client
function MyComponent() {
const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>;
}
// ✅ Fixed: Use state and useEffect to handle client-side logic post-hydration
function MyComponent() {
const [isMobile, setIsMobile] = useState(false);
useEffect(() => {
setIsMobile(window.innerWidth < 768);
}, []);
// Initial render matches server, then updates on client
return <div>{isMobile ? 'Mobile' : 'Desktop'}</div>;
}