Problem
PR #834 uses useState(checkExpired) as a lazy initializer, which calls Date.now() during the initial render. Server and client timestamps differ, causing a potential React hydration mismatch warning for storylines near the expiry boundary.
Also: the 1-second setInterval polling is wasteful for a badge that only transitions once (active → expired). A setTimeout targeting the exact expiry time would be more efficient.
Solution
- Change
useState(checkExpired) to useState(false) — let the existing useEffect set the correct value on mount
- Replace
setInterval(1000) with setTimeout calculated from expiryTime - Date.now()
Acceptance Criteria
Branch
task/<issue>-badge-hydration-fix
Problem
PR #834 uses
useState(checkExpired)as a lazy initializer, which callsDate.now()during the initial render. Server and client timestamps differ, causing a potential React hydration mismatch warning for storylines near the expiry boundary.Also: the 1-second
setIntervalpolling is wasteful for a badge that only transitions once (active → expired). AsetTimeouttargeting the exact expiry time would be more efficient.Solution
useState(checkExpired)touseState(false)— let the existinguseEffectset the correct value on mountsetInterval(1000)withsetTimeoutcalculated fromexpiryTime - Date.now()Acceptance Criteria
Branch
task/<issue>-badge-hydration-fix