It happens when the server-rendered HTML differs from the client’s first render (e.g., `Math.random()`, `Date.now()`, `window` branches, locale formatting). Fix by making initial render deterministic or moving client-only values to `useEffect`/client components.
Advanced answer
Deep dive
Hydration is React attaching event listeners and reconciling the server-rendered HTML with the first client render. A mismatch happens when the HTML generated on the server is not the same as what the client renders initially.
Common causes
Non-deterministic values during render: `Math.random()`, `Date.now()`, `crypto.randomUUID()`.
Browser-only branches: `typeof window !== 'undefined'` during render.