From a74814bd9b67c9f6e0a8643de05773cfb14cbdc9 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Mon, 16 Mar 2026 11:52:21 +0000 Subject: [PATCH] [#155] Fix DeadlineCountdown hydration mismatch Always initialize remaining as null so server and client both render the placeholder during hydration. Set the value in useEffect after mount. The lint rule is suppressed for the initial sync setState since this is the correct SSR hydration pattern. Fixes #155 Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/DeadlineCountdown.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/DeadlineCountdown.tsx b/src/components/DeadlineCountdown.tsx index 871b4162..8b8d619d 100644 --- a/src/components/DeadlineCountdown.tsx +++ b/src/components/DeadlineCountdown.tsx @@ -5,11 +5,11 @@ import { useState, useEffect } from "react"; const DEADLINE_HOURS = 72; export function DeadlineCountdown({ lastPlotTime }: { lastPlotTime: string }) { - const [remaining, setRemaining] = useState(() => - typeof window === "undefined" ? null : calcRemaining(lastPlotTime), - ); + const [remaining, setRemaining] = useState(null); useEffect(() => { + // eslint-disable-next-line react-hooks/set-state-in-effect -- initial sync needed for SSR hydration safety + setRemaining(calcRemaining(lastPlotTime)); const interval = setInterval(() => { setRemaining(calcRemaining(lastPlotTime)); }, 1000);