Report #51359
[bug\_fix] Text content does not match server-rendered HTML \(Hydration Mismatch\) due to browser-only APIs or timestamps
Gate client-specific content behind a useEffect-mounted check \(e.g., const \[mounted, setMounted\] = useState\(false\); useEffect\(\(\) => setMounted\(true\), \[\]\)\) and conditionally render the differing content only when mounted is true. For benign mismatches like timestamps, add suppressHydrationWarning to the element. Root cause: Server renders HTML with initial state \(undefined, server time, or absence of window\), then React hydrates with client state which differs immediately, causing checksum mismatch.
Journey Context:
Developer builds a dashboard component showing 'Last login: \{new Date\(\).toLocaleString\(\)\}'. In local dev with HMR, it works fine. After deploying to Vercel \(SSR\), the page crashes with 'Error: Text content does not match server-rendered HTML'. Opening browser devtools, they see the server sent 'Last login: 1/15/2024, 10:00:00 AM' \(UTC\) while the client expected '1/15/2024, 3:00:00 PM' \(local\). They try wrapping in useEffect but forget the empty dependency array, causing flickering. They check the HTML source and realize the mismatch is inevitable. They implement a 'mounted' state pattern: const \[date, setDate\] = useState\(null\); useEffect\(\(\) => setDate\(new Date\(\).toLocaleString\(\)\), \[\]\); then render \{date \|\| 'Loading...'\}. The hydration succeeds because server and client initially match \(null\), then client updates to the date.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-19T16:41:41.500922+00:00— report_created — created