The Topology page crashed on load with React error #185 ("Maximum update depth exceeded"), thrown from inside React Flow's setNodes. Root cause: handleDeleteManual depended on the whole TanStack Query useMutation result object, which is recreated on every render. That made handleDeleteManual unstable, which made the `graph` useMemo recompute every render, which made the node/edge sync effect fire every render — calling setNodes/setEdges in a loop until React aborted. Fix: depend on the referentially-stable `.mutate` function instead of the whole mutation object, so handleDeleteManual stays stable and `graph` only rebuilds when the underlying data or connectMode actually change. Verified: tsc --noEmit clean, eslint clean, vite build succeeds, and the Topology page renders without #185 in a local Docker build. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
914ded24b0
commit
6dd855476e
@@ -516,10 +516,17 @@ export default function TopologyPage() {
|
|||||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['topology'] }),
|
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['topology'] }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Depend on the stable `.mutate` function rather than the whole mutation object.
|
||||||
|
// TanStack Query recreates the mutation result object on every render but keeps
|
||||||
|
// `.mutate` referentially stable, so this keeps handleDeleteManual stable too.
|
||||||
|
// Depending on the whole object would make handleDeleteManual — and therefore the
|
||||||
|
// `graph` memo and the node/edge sync effect below — re-run on every render,
|
||||||
|
// causing an infinite setNodes/setEdges loop (React error #185).
|
||||||
|
const deleteManualLinkMutate = deleteManualLinkMutation.mutate;
|
||||||
const handleDeleteManual = useCallback((edgeId: string) => {
|
const handleDeleteManual = useCallback((edgeId: string) => {
|
||||||
const id = parseInt(edgeId);
|
const id = parseInt(edgeId);
|
||||||
if (!isNaN(id)) deleteManualLinkMutation.mutate(id);
|
if (!isNaN(id)) deleteManualLinkMutate(id);
|
||||||
}, [deleteManualLinkMutation]);
|
}, [deleteManualLinkMutate]);
|
||||||
|
|
||||||
const [nodes, setNodes, onNodesChange] = useNodesState<Node>([]);
|
const [nodes, setNodes, onNodesChange] = useNodesState<Node>([]);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
|
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
|
||||||
|
|||||||
Reference in New Issue
Block a user