From e4ca70d758c306a8913bb237988388ee9de4dec7 Mon Sep 17 00:00:00 2001 From: david_bai Date: Sat, 28 Mar 2026 10:23:43 +0800 Subject: [PATCH] fix: resolve React hydration mismatch in ThemeToggle The ThemeToggle component was causing hydration errors because the server and client rendered different icons (Sun/Moon) based on the theme state. Changes: - Render a placeholder button until component is mounted - Only render the actual theme icon after client-side hydration - This ensures server and client HTML match during initial render Fixes console error: 'Expected server HTML to contain a matching in ' --- frontend/components/web/ThemeToggle.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/frontend/components/web/ThemeToggle.tsx b/frontend/components/web/ThemeToggle.tsx index ab29529..2f3664f 100644 --- a/frontend/components/web/ThemeToggle.tsx +++ b/frontend/components/web/ThemeToggle.tsx @@ -11,6 +11,19 @@ export default function ThemeToggle() { useEffect(() => setMounted(true), []); + if (!mounted) { + return ( + + + ); + } + const isDark = resolvedTheme === "dark"; const toggle = () => setTheme(isDark ? "light" : "dark"); @@ -20,7 +33,6 @@ export default function ThemeToggle() { size="icon" aria-label="Toggle theme" onClick={toggle} - disabled={!mounted} > {isDark ? : } Toggle theme