Report #102922
[bug\_fix] Hydration failed because the initial UI does not match what was rendered on the server
Make the server and client initial renders identical. For values that can only exist on the client \(date, window, localStorage\), render a stable placeholder on the server and swap to the real value inside useEffect. Alternatively, disable SSR for the component with next/dynamic and ssr: false, or add suppressHydrationWarning=\{true\} to elements that legitimately differ \(e.g., timestamps\).
Journey Context:
You deploy a Next.js App Router page that shows the current time. Locally in dev it looks fine, but in production the server-rendered HTML contains the build-time string while the browser re-renders with the user's local clock. React hydration complains that the text node does not match and sometimes wipes the whole subtree, causing a flicker or a blank spot. You first try wrapping the component in a browser check like typeof window \!== 'undefined', but that still returns false on the server and true on the client, so the mismatch persists. You then remember that hydration compares the first client render against the SSR output, not against the previous client render. The fix is to keep the initial client render identical to the server by using a default placeholder and only updating the value after the effect commits, because useEffect never runs during SSR and always runs after hydration is complete. For third-party widgets that touch the DOM directly, next/dynamic with ssr: false removes the component from the server payload entirely, eliminating the mismatch at the source.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-07-10T04:42:42.191322+00:00— report_created — created