Fix HistoryPage stale appliedQuery effect and add mount query regression test
This commit is contained in:
@@ -37,7 +37,7 @@ Issues are grouped by category and ordered roughly by severity. Each entry descr
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### TASK-002 — `HistoryPage` filter effect has a stale `appliedQuery` dependency
|
### TASK-002 — `HistoryPage` filter effect has a stale `appliedQuery` dependency (done)
|
||||||
|
|
||||||
**Where found:** `frontend/src/pages/HistoryPage.tsx` lines 214–230. The `useEffect` lists `appliedQuery` as a dependency, reads it inside the effect, and then calls `setAppliedQuery` — which triggers the same effect again immediately.
|
**Where found:** `frontend/src/pages/HistoryPage.tsx` lines 214–230. The `useEffect` lists `appliedQuery` as a dependency, reads it inside the effect, and then calls `setAppliedQuery` — which triggers the same effect again immediately.
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* Rows with repeatedly-banned IPs are highlighted in amber.
|
* Rows with repeatedly-banned IPs are highlighted in amber.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
@@ -199,10 +199,14 @@ export function HistoryPage(): React.JSX.Element {
|
|||||||
const [originFilter, setOriginFilter] = useState<BanOriginFilter>("all");
|
const [originFilter, setOriginFilter] = useState<BanOriginFilter>("all");
|
||||||
const [jailFilter, setJailFilter] = useState("");
|
const [jailFilter, setJailFilter] = useState("");
|
||||||
const [ipFilter, setIpFilter] = useState("");
|
const [ipFilter, setIpFilter] = useState("");
|
||||||
const [appliedQuery, setAppliedQuery] = useState<HistoryQuery>({
|
const defaultQuery: HistoryQuery = {
|
||||||
|
range: "7d",
|
||||||
source: "archive",
|
source: "archive",
|
||||||
page_size: PAGE_SIZE,
|
page_size: PAGE_SIZE,
|
||||||
});
|
page: 1,
|
||||||
|
};
|
||||||
|
const [appliedQuery, setAppliedQuery] = useState<HistoryQuery>(defaultQuery);
|
||||||
|
const appliedQueryRef = useRef<HistoryQuery>(defaultQuery);
|
||||||
|
|
||||||
// Per-IP detail navigation
|
// Per-IP detail navigation
|
||||||
const [selectedIp, setSelectedIp] = useState<string | null>(null);
|
const [selectedIp, setSelectedIp] = useState<string | null>(null);
|
||||||
@@ -221,13 +225,14 @@ export function HistoryPage(): React.JSX.Element {
|
|||||||
page_size: PAGE_SIZE,
|
page_size: PAGE_SIZE,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (areHistoryQueriesEqual(nextQuery, appliedQuery)) {
|
if (areHistoryQueriesEqual(nextQuery, appliedQueryRef.current)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPage(1);
|
setPage(1);
|
||||||
setAppliedQuery(nextQuery);
|
setAppliedQuery(nextQuery);
|
||||||
}, [range, originFilter, jailFilter, ipFilter, setPage, appliedQuery]);
|
appliedQueryRef.current = nextQuery;
|
||||||
|
}, [range, originFilter, jailFilter, ipFilter, setPage]);
|
||||||
|
|
||||||
const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
|
const totalPages = Math.max(1, Math.ceil(total / PAGE_SIZE));
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ vi.mock("../../components/WorldMap", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("../../api/config", () => ({
|
vi.mock("../../api/config", () => ({
|
||||||
fetchMapColorThresholds: async () => ({
|
fetchMapColorThresholds: () => ({
|
||||||
threshold_low: 10,
|
threshold_low: 10,
|
||||||
threshold_medium: 50,
|
threshold_medium: 50,
|
||||||
threshold_high: 100,
|
threshold_high: 100,
|
||||||
@@ -74,4 +74,18 @@ describe("HistoryPage", () => {
|
|||||||
expect(lastQuery).toMatchObject({ origin: "blocklist" });
|
expect(lastQuery).toMatchObject({ origin: "blocklist" });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("never calls history without the default range on mount", async () => {
|
||||||
|
render(
|
||||||
|
<FluentProvider theme={webLightTheme}>
|
||||||
|
<HistoryPage />
|
||||||
|
</FluentProvider>,
|
||||||
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(lastQuery?.range).toBe("7d");
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockUseHistory.mock.calls.every((call) => call[0].range === "7d")).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user