From 3c4789462801a61f6111ca3b0aaeb6d01049bcd2 Mon Sep 17 00:00:00 2001 From: Myron Blair Date: Sun, 26 Jul 2026 21:07:40 -0500 Subject: [PATCH] Fix Library Scan tab race condition mixing results across kinds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switching tabs quickly (e.g. Movies -> Music) had no guard against an in-flight response from the previous tab resolving late and overwriting the new tab's results — showing movie/TV rips under the Music tab. Now tracks a request sequence number and ignores stale responses, and clears results immediately on tab switch so nothing renders under the wrong label. --- frontend/src/pages/LibraryScan.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/frontend/src/pages/LibraryScan.jsx b/frontend/src/pages/LibraryScan.jsx index 78c48ae..7546750 100644 --- a/frontend/src/pages/LibraryScan.jsx +++ b/frontend/src/pages/LibraryScan.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import api from "../lib/api"; import { toast } from "sonner"; import { RefreshCcw, Download, Check, Sparkles, CheckSquare, Square } from "lucide-react"; @@ -16,21 +16,25 @@ export default function LibraryScan() { const [loading, setLoading] = useState(false); const [importing, setImporting] = useState(false); const [enrich, setEnrich] = useState(null); + const requestSeq = useRef(0); const load = async (k = kind) => { + const seq = ++requestSeq.current; setLoading(true); setSelected(new Set()); try { const { data } = await api.get(`/scan/${k}`); + if (seq !== requestSeq.current) return; // a newer tab switch/rescan superseded this response setResults(data); } catch (err) { + if (seq !== requestSeq.current) return; toast.error(err.response?.data?.detail || "Scan failed"); } finally { - setLoading(false); + if (seq === requestSeq.current) setLoading(false); } }; - useEffect(() => { load(kind); }, [kind]); + useEffect(() => { setResults([]); load(kind); }, [kind]); useEffect(() => { if (!enrich?.running) return;