Report #71030
[bug\_fix] Hydration failed because the initial UI does not match what was rendered on the server \(due to Date, Math.random, or window check in render\)
Move dynamic values into useEffect so server renders a stable placeholder \(null or static string\), and client updates after hydration. This ensures the initial HTML sent by the server matches the client's first paint before hydration attaches.
Journey Context:
Developer adds a timestamp like \`\{new Date\(\).toLocaleTimeString\(\)\}\` directly in the JSX of a Next.js page. In development \(client-side navigation\), it works fine. After building and deploying, hard refreshing the page throws a hydration error in the console: 'Text content does not match: Server: "10:00 AM" Client: "3:00 PM"'. Developer suspects timezone issues and tries forcing UTC on the server, but the mismatch persists because the server clock and client clock will never be identical, and hydration requires bitwise-identical HTML. Developer tries \`suppressHydrationWarning\`, which silences the error but causes a visible flicker as the time updates after load. The debugging rabbit hole leads to realizing that any value that differs between server and client \(Date, Math.random, window size\) must be rendered only on the client using useEffect.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T01:48:16.075990+00:00— report_created — created