Live wall review fixes: no not-found flash or map whiplash when the selected incident resolves (#239)

useIncident reports loading until its answer belongs to the current id
(the render before the effect read the previous id's loading=false), and
clears a stale doc on a denied read. LiveView holds the last selected doc
for the same id while the by-id lookup is pending, so a watched incident
resolving no longer deselects (fly to region) and reselects (fly back).

Follow-up for the panel's 'active'/elapsed copy on resolved incidents: #275.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Logan Cusano
2026-10-05 03:29:58 -04:00
co-authored by Claude Opus 5.5
parent a267fdf982
commit 7a0e86decf
2 changed files with 16 additions and 5 deletions
+9 -4
View File
@@ -86,17 +86,19 @@ export function useIncidents(limitCount = 100, dateFrom?: Date, dateTo?: Date) {
export function useIncident(incidentId: string | null) {
const [incident, setIncident] = useState<IncidentRecord | null>(null);
const [loading, setLoading] = useState(true);
// The id the current `incident`/`loading` answer belongs to. On the render
// where the id changes the effect hasn't run yet, so `loading` alone would
// still read false from the previous id and a caller would flash "not found".
const [settledId, setSettledId] = useState<string | null>(null);
useEffect(() => {
if (!incidentId) { setLoading(false); return; }
// A new id is a new lookup: without this, `loading` stays false from the
// previous id and a caller reads "not found" until the snapshot lands.
setLoading(true);
let unsubFirestore: (() => void) | undefined;
const unsubAuth = onAuthStateChanged(auth, (user) => {
if (unsubFirestore) { unsubFirestore(); unsubFirestore = undefined; }
if (!user) { setLoading(false); return; }
if (!user) { setLoading(false); setSettledId(incidentId); return; }
const ref = doc(db, "incidents", incidentId);
unsubFirestore = onSnapshot(ref, (snap) => {
@@ -111,16 +113,19 @@ export function useIncident(incidentId: string | null) {
setIncident(null);
}
setLoading(false);
setSettledId(incidentId);
}, (err: FirestoreError) => {
console.error("useIncident:", err);
setIncident(null); // a denied/failed read must not leave the previous id's doc
setLoading(false);
setSettledId(incidentId);
});
});
return () => { unsubAuth(); if (unsubFirestore) unsubFirestore(); };
}, [incidentId]);
return { incident, loading };
return { incident, loading: loading || (!!incidentId && settledId !== incidentId) };
}
export function useActiveIncidents() {