diff --git a/web/sections/CollectionsPanel.tsx b/web/sections/CollectionsPanel.tsx index 606ec7f..458409c 100644 --- a/web/sections/CollectionsPanel.tsx +++ b/web/sections/CollectionsPanel.tsx @@ -61,15 +61,42 @@ export const CollectionsPanel = () => { void load(); }, [load]); - // The folder's contents, re-read when the selection moves. Null while nothing is chosen, so the + /* + A selection naming something that is not there any more. + + The id lives in the URL, so it outlives the row: delete a collection with it open, reload, and the + address still asks for it. Left alone that became a 404 from the media fetch, rendered as "Not + found" over a panel that was otherwise working — an error about the URL, phrased as an error about + the server. + + Dropped rather than reported. There is nothing for anybody to do about it and the correct state is + simply "nothing selected". + */ + useEffect(() => { + if (!collections || !selectedId) return; + if (collections.some((one) => one.id === selectedId)) return; + setParams( + (current) => { + const next = new URLSearchParams(current); + next.delete('collection'); + return next; + }, + { replace: true }, + ); + }, [collections, selectedId, setParams]); + + // The gallery's photographs, re-read when the selection moves. Null while nothing is chosen, so the // empty state and "still loading" are not the same thing. useEffect(() => { - if (!selectedId) { + if (!selectedId || !selected) { setPhotos(null); return; } let alive = true; setPhotos(null); + // Cleared here rather than only on success: an error from the last selection has nothing to say + // about this one, and leaving it up reads as the new one having failed too. + setError(null); void clientRef.current .get<{ data: CollectionPhoto[] }>(`/fofos-admin/collections/${selectedId}/media`) .then((response) => alive && setPhotos(response.data)) @@ -77,7 +104,7 @@ export const CollectionsPanel = () => { return () => { alive = false; }; - }, [selectedId]); + }, [selectedId, selected]); /* The fields, in the editor column — a SIBLING panel, so they are announced rather than rendered.