From 00a13e3289c38ad1fa340f325f480828b5041601 Mon Sep 17 00:00:00 2001 From: "D. Rimron-Soutter" Date: Sun, 11 Jan 2026 13:30:10 +0000 Subject: [PATCH] Fix explorer hook deps Resolve hook dependency warnings in entries and releases explorers. Signed-off-by: codex@lucy.xalior.com --- src/app/zxdb/entries/EntriesExplorer.tsx | 3 +- src/app/zxdb/releases/ReleasesExplorer.tsx | 68 +++++++++++++--------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/app/zxdb/entries/EntriesExplorer.tsx b/src/app/zxdb/entries/EntriesExplorer.tsx index a651650..3e548f5 100644 --- a/src/app/zxdb/entries/EntriesExplorer.tsx +++ b/src/app/zxdb/entries/EntriesExplorer.tsx @@ -9,6 +9,8 @@ import ExplorerLayout from "@/components/explorer/ExplorerLayout"; import FilterSidebar from "@/components/explorer/FilterSidebar"; import MultiSelectChips from "@/components/explorer/MultiSelectChips"; +const preferredMachineIds = [27, 26, 8, 9]; + type Item = { id: number; title: string; @@ -60,7 +62,6 @@ export default function EntriesExplorer({ scope?: SearchScope; }; }) { - const preferredMachineIds = [27, 26, 8, 9]; const parseMachineIds = (value?: string) => { if (!value) return preferredMachineIds.slice(); const ids = value diff --git a/src/app/zxdb/releases/ReleasesExplorer.tsx b/src/app/zxdb/releases/ReleasesExplorer.tsx index a7981aa..8998308 100644 --- a/src/app/zxdb/releases/ReleasesExplorer.tsx +++ b/src/app/zxdb/releases/ReleasesExplorer.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import Link from "next/link"; import EntryLink from "../components/EntryLink"; import { usePathname, useRouter } from "next/navigation"; @@ -9,6 +9,17 @@ import ExplorerLayout from "@/components/explorer/ExplorerLayout"; import FilterSidebar from "@/components/explorer/FilterSidebar"; import MultiSelectChips from "@/components/explorer/MultiSelectChips"; +const preferredMachineIds = [27, 26, 8, 9]; + +function parseMachineIds(value?: string) { + if (!value) return preferredMachineIds.slice(); + const ids = value + .split(",") + .map((id) => Number(id.trim())) + .filter((id) => Number.isFinite(id) && id > 0); + return ids.length ? ids : preferredMachineIds.slice(); +} + type Item = { entryId: number; releaseSeq: number; @@ -54,16 +65,6 @@ export default function ReleasesExplorer({ casetypes: { id: string; name: string }[]; }; }) { - const preferredMachineIds = [27, 26, 8, 9]; - const parseMachineIds = (value?: string) => { - if (!value) return preferredMachineIds.slice(); - const ids = value - .split(",") - .map((id) => Number(id.trim())) - .filter((id) => Number.isFinite(id) && id > 0); - return ids.length ? ids : preferredMachineIds.slice(); - }; - const router = useRouter(); const pathname = usePathname(); @@ -106,7 +107,7 @@ export default function ReleasesExplorer({ const pageSize = 20; const totalPages = useMemo(() => (data ? Math.max(1, Math.ceil(data.total / data.pageSize)) : 1), [data]); - function updateUrl(nextPage = page) { + const updateUrl = useCallback((nextPage = page) => { const params = new URLSearchParams(); if (appliedQ) params.set("q", appliedQ); params.set("page", String(nextPage)); @@ -121,9 +122,9 @@ export default function ReleasesExplorer({ if (isDemo) params.set("isDemo", "1"); const qs = params.toString(); router.replace(qs ? `${pathname}?${qs}` : pathname); - } + }, [appliedQ, casetypeId, dLanguageId, dMachinetypeIds, filetypeId, isDemo, page, pathname, router, schemetypeId, sort, sourcetypeId, year]); - async function fetchData(query: string, p: number) { + const fetchData = useCallback(async (query: string, p: number) => { setLoading(true); try { const params = new URLSearchParams(); @@ -149,7 +150,7 @@ export default function ReleasesExplorer({ } finally { setLoading(false); } - } + }, [casetypeId, dLanguageId, dMachinetypeIds, filetypeId, isDemo, pageSize, schemetypeId, sort, sourcetypeId, year]); useEffect(() => { if (initial) { @@ -158,21 +159,34 @@ export default function ReleasesExplorer({ } }, [initial]); + const initialState = useMemo(() => ({ + q: initialUrlState?.q ?? "", + year: initialUrlState?.year ?? "", + sort: initialUrlState?.sort ?? "year_desc", + dLanguageId: initialUrlState?.dLanguageId ?? "", + dMachinetypeId: initialUrlState?.dMachinetypeId ?? "", + filetypeId: initialUrlState?.filetypeId ?? "", + schemetypeId: initialUrlState?.schemetypeId ?? "", + sourcetypeId: initialUrlState?.sourcetypeId ?? "", + casetypeId: initialUrlState?.casetypeId ?? "", + isDemo: initialUrlState?.isDemo, + }), [initialUrlState]); + useEffect(() => { const initialPage = initial?.page ?? 1; if ( initial && page === initialPage && - (initialUrlState?.q ?? "") === appliedQ && - (initialUrlState?.year ?? "") === (year ?? "") && - sort === (initialUrlState?.sort ?? "year_desc") && - (initialUrlState?.dLanguageId ?? "") === dLanguageId && - parseMachineIds(initialUrlState?.dMachinetypeId).join(",") === dMachinetypeIds.join(",") && - (initialUrlState?.filetypeId ?? "") === filetypeId && - (initialUrlState?.schemetypeId ?? "") === schemetypeId && - (initialUrlState?.sourcetypeId ?? "") === sourcetypeId && - (initialUrlState?.casetypeId ?? "") === casetypeId && - (!!initialUrlState?.isDemo === isDemo) + initialState.q === appliedQ && + initialState.year === (year ?? "") && + sort === initialState.sort && + initialState.dLanguageId === dLanguageId && + parseMachineIds(initialState.dMachinetypeId).join(",") === dMachinetypeIds.join(",") && + initialState.filetypeId === filetypeId && + initialState.schemetypeId === schemetypeId && + initialState.sourcetypeId === sourcetypeId && + initialState.casetypeId === casetypeId && + (!!initialState.isDemo === isDemo) ) { if (initialLoad.current) { initialLoad.current = false; @@ -187,7 +201,7 @@ export default function ReleasesExplorer({ } updateUrl(page); fetchData(appliedQ, page); - }, [page, year, sort, dLanguageId, dMachinetypeIds, filetypeId, schemetypeId, sourcetypeId, casetypeId, isDemo, appliedQ]); + }, [appliedQ, casetypeId, dLanguageId, dMachinetypeIds, fetchData, filetypeId, initial, initialState, initialUrlHasParams, isDemo, page, schemetypeId, sort, sourcetypeId, updateUrl, year]); function onSubmit(e: React.FormEvent) { e.preventDefault(); @@ -219,7 +233,7 @@ export default function ReleasesExplorer({ } } loadLists(); - }, []); + }, [cases.length, filetypes.length, langs.length, machines.length, schemes.length, sources.length]); const prevHref = useMemo(() => { const params = new URLSearchParams();