fix(audit-log): stop replaying the page entrance animation on every filter

AuditLog uses a raw useQuery with the filters in the queryKey and a page-level early return (if isPending && no rows → <LoadingState/>), which sits ABOVE <PageEnter>. On any filter change the new queryKey had no cached data, so isPending flipped true with empty rows, the early return unmounted the whole PageEnter subtree, and it remounted (replaying the staggered entrance) when data arrived. Add placeholderData: keepPreviousData so rows persist through the refetch (isPending stays false, subtree never unmounts), and dim the table via isFetching instead of isPending. Verified by DOM node-identity: the PageEnter root survives a filter (no remount). The paginated list pages were already immune (usePaginatedQuery bakes in keepPreviousData).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-06-07 15:34:06 +02:00
parent c4e71475ce
commit b23d15453d

View File

@@ -1,5 +1,5 @@
import { useState } from "react";
import { useQuery } from "@tanstack/react-query";
import { useQuery, keepPreviousData } from "@tanstack/react-query";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import { useAuth } from "../context/AuthContext";
@@ -128,7 +128,11 @@ export default function AuditLog() {
// cleanupDays stored as string for the kit Select; converted to number at the boundary
const [cleanupDaysStr, setCleanupDaysStr] = useState("90");
const { data: logsData, isPending } = useQuery({
const {
data: logsData,
isPending,
isFetching,
} = useQuery({
queryKey: [
"audit-log",
{
@@ -169,6 +173,10 @@ export default function AuditLog() {
},
};
},
// Keep the current rows on screen while a filter refetches, so the page
// doesn't drop to <LoadingState/> (which unmounts PageEnter and replays the
// whole entrance animation on every filter change).
placeholderData: keepPreviousData,
});
const logs: AuditLogEntry[] = logsData?.data ?? [];
@@ -352,7 +360,7 @@ export default function AuditLog() {
</Box>
</FilterBar>
<Card sx={{ opacity: isPending ? 0.6 : 1, transition: "opacity .2s" }}>
<Card sx={{ opacity: isFetching ? 0.6 : 1, transition: "opacity .2s" }}>
<DataTable<AuditLogEntry>
columns={columns}
rows={logs}