fix(v2): inventory no longer flickers — debounced re-fetch, no loading flash

inventory_delta WS messages were triggering immediate full re-fetch
with setLoading(true), causing content to flash blank. Now:
- Initial load shows loading state (once)
- Subsequent deltas debounced to 2s (batches rapid changes)
- Re-fetch runs silently without clearing existing items

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-04-14 13:54:06 +02:00
parent 0112c59514
commit 4638e60043

View file

@ -163,19 +163,33 @@ export const InventoryWindow: React.FC<Props> = ({ id, charName, zIndex, invento
const [activePack, setActivePack] = useState<number | null>(null);
const [tooltip, setTooltip] = useState<{ item: any; x: number; y: number } | null>(null);
const [charStats, setCharStats] = useState<any>(null);
const [cantripState, setCantripState] = useState<any>(null);
const debounceRef = useRef<number>(0);
const initialLoadDone = useRef(false);
// Initial fetch
useEffect(() => {
setLoading(true);
Promise.all([
apiFetch<any>(`/inventory/${encodeURIComponent(charName)}?limit=1000`).catch(() => ({ items: [] })),
apiFetch<any>(`/character-stats/${encodeURIComponent(charName)}`).catch(() => null),
]).then(([inv, stats]) => {
const rawItems = inv.items ?? [];
setItems(rawItems.map(normalizeItem));
setItems((inv.items ?? []).map(normalizeItem));
setCharStats(stats);
initialLoadDone.current = true;
}).finally(() => setLoading(false));
}, [charName, inventoryVersion]); // re-fetch when inventory_delta arrives
}, [charName]);
// Debounced re-fetch on inventory_delta (no loading flash)
useEffect(() => {
if (!initialLoadDone.current || !inventoryVersion) return;
clearTimeout(debounceRef.current);
debounceRef.current = window.setTimeout(() => {
apiFetch<any>(`/inventory/${encodeURIComponent(charName)}?limit=1000`)
.then(inv => setItems((inv.items ?? []).map(normalizeItem)))
.catch(() => {});
}, 2000); // 2s debounce — batch rapid deltas
return () => clearTimeout(debounceRef.current);
}, [charName, inventoryVersion]);
const handleHover = useCallback((item: any | null, e?: React.MouseEvent) => {
if (item && e) setTooltip({ item, x: e.clientX, y: e.clientY });