diff --git a/ui/src/App.jsx b/ui/src/App.jsx index 64021e6..940a101 100644 --- a/ui/src/App.jsx +++ b/ui/src/App.jsx @@ -13,6 +13,7 @@ export default function App() { const [sourcesLoaded, setSourcesLoaded] = useState(false) const [sourceId, setSourceId] = useState(() => localStorage.getItem('pf_sourceId') || '') const [versions, setVersions] = useState([]) + const [versionsLoaded, setVersionsLoaded] = useState(false) const [versionId, setVersionId] = useState(() => localStorage.getItem('pf_versionId') || '') useEffect(() => { localStorage.setItem('pf_view', view) }, [view]) @@ -30,10 +31,11 @@ export default function App() { const refreshVersions = useCallback(async (sid) => { const id = sid ?? sourceId - if (!id) { setVersions([]); return [] } + if (!id) { setVersions([]); setVersionsLoaded(true); return [] } const data = await fetch(`/api/sources/${id}/versions`).then(r => r.json()) const list = Array.isArray(data) ? data : [] setVersions(list) + setVersionsLoaded(true) return list }, [sourceId]) @@ -52,18 +54,26 @@ export default function App() { }, [sources, sourcesLoaded, sourceId]) useEffect(() => { - if (!sourceId) { setVersions([]); setVersionId(''); return } + if (!sourceId) { setVersions([]); setVersionId(''); setVersionsLoaded(true); return } + // The list belongs to the previous source until the fetch lands. + setVersionsLoaded(false) refreshVersions(sourceId) }, [sourceId]) // Same reasoning as sources: a deleted version must not stay selected. + // + // versionsLoaded matters more than it looks: without it, the empty initial + // state reads as "this source has no versions", so a versionId restored from + // localStorage is cleared and then set straight back when the fetch lands. + // Forecast's load effect is keyed on that id, so the round trip made every + // page load fetch and aggregate the whole version twice. useEffect(() => { - if (!sourceId) return + if (!sourceId || !versionsLoaded) return if (versions.length === 0) { setVersionId(''); return } if (!versionId || !versions.some(v => String(v.id) === String(versionId))) { setVersionId(String(versions[0].id)) } - }, [versions, sourceId, versionId]) + }, [versions, versionsLoaded, sourceId, versionId]) const ctx = { sources, sourceId, setSourceId,