Files
stack/packages/mosaic/framework/skills/next-best-practices/hydration-error.md
T
fargo 1a822493ba format: apply repo prettier (3.8.1) to the folded skills tree
963 markdown files reformatted with the repository's pinned prettier so
pnpm format:check covers the folded tree like every other repo file.

The formatter's embedded-language pass also normalized code fences
(TS semicolons, closed HTML tags in examples, lowercased CSS hex colors,
one renumbered list that skipped an index). Alphanumeric token deltas vs
the fold commit were audited file-by-file; all are formatter-equivalent
markup normalizations plus the four sanitized skills.
2026-08-19 14:37:17 -05:00

1.7 KiB

Hydration Errors

Diagnose and fix React hydration mismatch errors.

Error Signs

  • "Hydration failed because the initial UI does not match"
  • "Text content does not match server-rendered HTML"

Debugging

In development, click the hydration error to see the server/client diff.

Common Causes and Fixes

Browser-only APIs

// Bad: Causes mismatch - window doesn't exist on server
<div>{window.innerWidth}</div>;

// Good: Use client component with mounted check
('use client');
import { useState, useEffect } from 'react';

export function ClientOnly({ children }: { children: React.ReactNode }) {
  const [mounted, setMounted] = useState(false);
  useEffect(() => setMounted(true), []);
  return mounted ? children : null;
}

Date/Time Rendering

Server and client may be in different timezones:

// Bad: Causes mismatch
<span>{new Date().toLocaleString()}</span>;

// Good: Render on client only
('use client');
const [time, setTime] = useState<string>();
useEffect(() => setTime(new Date().toLocaleString()), []);

Random Values or IDs

// Bad: Random values differ between server and client
<div id={Math.random().toString()}>

// Good: Use useId hook
import { useId } from 'react'

function Input() {
  const id = useId()
  return <input id={id} />
}

Invalid HTML Nesting

// Bad: Invalid - div inside p
<p><div>Content</div></p>

// Bad: Invalid - p inside p
<p><p>Nested</p></p>

// Good: Valid nesting
<div><p>Content</p></div>

Third-party Scripts

Scripts that modify DOM during hydration.

// Good: Use next/script with afterInteractive
import Script from 'next/script';

export default function Page() {
  return <Script src="https://example.com/script.js" strategy="afterInteractive" />;
}