Merge chore/code-hygiene: fix Plex infinite-scroll dead after drill-in→Back

Callback-ref the grid's IntersectionObserver sentinel so it re-attaches on the
grid's unmount/remount cycle (drill into info/show/season → Back), instead of
observing a detached old node and freezing the feed at the loaded pages.
This commit is contained in:
npeter83 2026-07-12 00:16:54 +02:00
commit 1df6ddd154

View file

@ -156,21 +156,24 @@ export default function PlexBrowse({
// Episode matches (grouped "Episodes" section) — search-only; same set on every page, take page 0.
const episodes = browseQ.data?.pages[0]?.episodes ?? [];
// Infinite scroll: auto-load the next page when the sentinel scrolls into view.
const sentinel = useRef<HTMLDivElement>(null);
// Infinite scroll: auto-load the next page when the sentinel scrolls into view. The sentinel lives
// in the grid branch, which UNMOUNTS when we drill into an info/show/season page and remounts on
// Back — as a NEW element. A callback ref (state, not useRef) re-runs this effect on every
// mount/unmount, so the observer always watches the live node; a plain ref would keep observing the
// detached old node after Back and never fire fetchNextPage again (feed stuck at the loaded pages).
const [sentinelEl, setSentinelEl] = useState<HTMLDivElement | null>(null);
const { hasNextPage, isFetchingNextPage, fetchNextPage } = browseQ;
useEffect(() => {
const el = sentinel.current;
if (!el) return;
if (!sentinelEl) return;
const io = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && hasNextPage && !isFetchingNextPage) fetchNextPage();
},
{ rootMargin: "600px" },
);
io.observe(el);
io.observe(sentinelEl);
return () => io.disconnect();
}, [hasNextPage, isFetchingNextPage, fetchNextPage]);
}, [sentinelEl, hasNextPage, isFetchingNextPage, fetchNextPage]);
function onCard(card: PlexCard) {
scrollRef.current = scroller()?.scrollTop ?? 0; // remember grid position for the trip back
@ -345,7 +348,7 @@ export default function PlexBrowse({
</>
)}
<div ref={sentinel} className="h-8" />
<div ref={setSentinelEl} className="h-8" />
{isFetchingNextPage && <p className="text-center text-xs text-muted pb-4">{t("plex.loading")}</p>}
</div>
);