From 2f63188a345ce8e337723045a60b3a9306a9a840 Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Mon, 11 May 2026 10:03:40 +0200 Subject: [PATCH] fix(events): TDZ ReferenceError on /admin/events from #442 fix (#454) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pagination-clamp useEffect added in #448 (commit 9c4a96f) was inserted at the top of the component body, BEFORE the useQuery that declares `data`. Because the useEffect's dependency array `[data?.pagination, page]` is evaluated immediately when that line executes, every render hit a temporal dead zone access on `data` and threw `ReferenceError: Cannot access 'data' before initialization` — minified to "Cannot access 'I' before initialization" in the production bundle, crashing the entire page. TypeScript caught this at the time (`Block-scoped variable 'data' used before its declaration`) but the project's build doesn't fail on TS errors so it shipped anyway. Move the effect to immediately after the useQuery so `data` is in scope. Behavior unchanged otherwise — same dep array, same setPage clamp logic. Reported by @derooijmnl on v3.45.1-beta.0. --- frontend/src/pages/admin/EventsListPage.tsx | 25 ++++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/frontend/src/pages/admin/EventsListPage.tsx b/frontend/src/pages/admin/EventsListPage.tsx index 0b8b293a..57379a6a 100644 --- a/frontend/src/pages/admin/EventsListPage.tsx +++ b/frontend/src/pages/admin/EventsListPage.tsx @@ -104,17 +104,6 @@ export const EventsListPage: React.FC = () => { setPage(1); }, [statusFilter, debouncedSearchTerm]); - // Clamp the active page when the result count shrinks (#442 — bulk - // delete of an entire page would leave the user on a now-empty - // page=N where N > totalPages, with no auto-correction). Triggers - // after each successful refetch when totalPages drops below the - // current page (bulk delete, individual delete, archive, anything). - useEffect(() => { - if (data?.pagination && page > data.pagination.totalPages) { - setPage(Math.max(1, data.pagination.totalPages)); - } - }, [data?.pagination, page]); - // Close dropdown when clicking outside useEffect(() => { const handleClickOutside = (event: MouseEvent) => { @@ -157,6 +146,20 @@ export const EventsListPage: React.FC = () => { placeholderData: (prev) => prev, }); + // Clamp the active page when the result count shrinks (#442 — bulk + // delete of an entire page would leave the user on a now-empty + // page=N where N > totalPages, with no auto-correction). Triggers + // after each successful refetch when totalPages drops below the + // current page (bulk delete, individual delete, archive, anything). + // Must live AFTER the useQuery above so `data` is in scope — the + // original placement at the top of the component caused a TDZ + // ReferenceError on /admin/events that crashed the page (#454). + useEffect(() => { + if (data?.pagination && page > data.pagination.totalPages) { + setPage(Math.max(1, data.pagination.totalPages)); + } + }, [data?.pagination, page]); + // Aggregate counters come from the dashboard stats endpoint so the cards // and the "All (N)" filter button always reflect global totals, not the // currently visible page.