Fix max update depth crash on Infrastructure page
CI / build-and-push (push) Successful in 34s

ToastContainer's useEffect had `seen` (a Set state) in its dependency
array — each setSeen created a new Set, re-fired the effect, and under
rapid notifications cascaded past React's 50-update limit. Replaced
with a ref since seen doesn't need to trigger re-renders.

Also added useShallow to DataCenterCard's pipeline selector to prevent
.filter() from causing spurious re-renders on unrelated store changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-24 20:29:54 -04:00
parent 24278297f0
commit a36617f9e3
2 changed files with 8 additions and 11 deletions
@@ -1,4 +1,4 @@
import { useEffect, useState } from 'react';
import { useEffect, useState, useRef } from 'react';
import { X, CheckCircle, AlertTriangle, Info, AlertCircle } from 'lucide-react';
import { useGameStore, type GameNotification } from '@/store';
@@ -10,23 +10,19 @@ export function ToastContainer() {
const notifications = useGameStore((s) => s.notifications);
const dismissNotification = useGameStore((s) => s.dismissNotification);
const [toasts, setToasts] = useState<Toast[]>([]);
const [seen, setSeen] = useState(new Set<string>());
const seenRef = useRef(new Set<string>());
useEffect(() => {
const newNotifs = notifications.filter(n => !n.read && !seen.has(n.id));
const newNotifs = notifications.filter(n => !n.read && !seenRef.current.has(n.id));
if (newNotifs.length === 0) return;
setSeen(prev => {
const next = new Set(prev);
for (const n of newNotifs) next.add(n.id);
return next;
});
for (const n of newNotifs) seenRef.current.add(n.id);
setToasts(prev => [
...newNotifs.map(n => ({ ...n, exiting: false })),
...prev,
].slice(0, 5));
}, [notifications, seen]);
}, [notifications]);
useEffect(() => {
if (toasts.length === 0) return;