From e9ddf27eab6cc8ce2fe236bf63d0060c87e17eba Mon Sep 17 00:00:00 2001 From: le king fu Date: Sat, 30 May 2026 14:57:44 -0400 Subject: [PATCH] chore(web): document set-state-in-effect on ThemeToggle localStorage read (#90) ThemeToggle's mount effect reads localStorage then setTheme, a pattern react-hooks/set-state-in-effect flags. It is safe here: localStorage is SSR-unavailable so the read must happen post-mount, and ThemeScript already applies the dark class before hydration (no page FOUC). Add a targeted eslint-disable-next-line with justification. web/ lint is now green (0 errors). Co-Authored-By: Claude Opus 4.8 (1M context) --- web/src/components/ThemeToggle.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/web/src/components/ThemeToggle.tsx b/web/src/components/ThemeToggle.tsx index 4a2dd24..d6bd9e4 100644 --- a/web/src/components/ThemeToggle.tsx +++ b/web/src/components/ThemeToggle.tsx @@ -12,6 +12,11 @@ export function ThemeToggle() { useEffect(() => { const stored = localStorage.getItem("sl-theme") as Theme | null; + // localStorage is unavailable during SSR, so the stored theme can only be + // read post-mount. ThemeScript already applies the `dark` class before + // hydration (no page FOUC); only the toggle icon corrects on mount. The + // rule is a false positive for this hydration-from-localStorage read. + // eslint-disable-next-line react-hooks/set-state-in-effect if (stored) setTheme(stored); }, []);