From ede591c89e4689fff19777b6e5d0ea72c788f68e Mon Sep 17 00:00:00 2001 From: denshooter Date: Sat, 10 Jan 2026 18:28:25 +0100 Subject: [PATCH] Fix ActivityFeed hydration error: Move localStorage read to useEffect to prevent server/client mismatch --- app/components/ActivityFeed.tsx | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/app/components/ActivityFeed.tsx b/app/components/ActivityFeed.tsx index a8653b3..d23271d 100644 --- a/app/components/ActivityFeed.tsx +++ b/app/components/ActivityFeed.tsx @@ -50,30 +50,34 @@ interface StatusData { } export default function ActivityFeed() { + const [mounted, setMounted] = useState(false); const [data, setData] = useState(null); const [isExpanded, setIsExpanded] = useState(true); const [isMinimized, setIsMinimized] = useState(false); const [hasActivity, setHasActivity] = useState(false); - const [isTrackingEnabled, setIsTrackingEnabled] = useState(() => { - // Check localStorage for tracking preference + // Initialize with default value to prevent hydration mismatch + const [isTrackingEnabled, setIsTrackingEnabled] = useState(true); + const [quote, setQuote] = useState<{ + content: string; + author: string; + } | null>(null); + + // Load tracking preference from localStorage after mount to prevent hydration mismatch + useEffect(() => { + setMounted(true); if (typeof window !== "undefined") { try { const stored = localStorage.getItem("activityTrackingEnabled"); - return stored !== "false"; // Default to true if not set + setIsTrackingEnabled(stored !== "false"); // Default to true if not set } catch (error) { // localStorage might be disabled if (process.env.NODE_ENV === 'development') { console.warn('Failed to read tracking preference:', error); } - return true; // Default to enabled + setIsTrackingEnabled(true); // Default to enabled } } - return true; - }); - const [quote, setQuote] = useState<{ - content: string; - author: string; - } | null>(null); + }, []); // Fetch data every 30 seconds (optimized to match server cache) useEffect(() => { @@ -1456,6 +1460,9 @@ export default function ActivityFeed() { } }; + // Don't render until mounted to prevent hydration mismatch + if (!mounted) return null; + // Don't render if tracking is disabled and no data if (!isTrackingEnabled && !data) return null;