fix(events): TDZ ReferenceError on /admin/events from #442 fix (#454)

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.
This commit is contained in:
Paul Nothaft
2026-05-11 10:03:40 +02:00
parent 49b36a0352
commit 2f63188a34
+14 -11
View File
@@ -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.