diff --git a/src/app/admin/ontology/ontology-graph.tsx b/src/app/admin/ontology/ontology-graph.tsx index af5ac75..1485a41 100644 --- a/src/app/admin/ontology/ontology-graph.tsx +++ b/src/app/admin/ontology/ontology-graph.tsx @@ -1,6 +1,6 @@ "use client" -import { useEffect, useMemo, useRef, useState } from "react" +import { memo, useEffect, useMemo, useRef, useState } from "react" import dagre from "dagre" import { zoom as d3Zoom, zoomIdentity, ZoomBehavior, ZoomTransform } from "d3-zoom" import { select as d3Select } from "d3-selection" @@ -139,7 +139,11 @@ function edgeHierarchyPath( return `M ${s.x} ${s.y + NODE_HEIGHT / 2} L ${t.x} ${t.y - NODE_HEIGHT / 2}` } -export function OntologyGraph({ schemas, edges, selectedId, onSelect, onClear, selectedEdgeType }: Props) { +// Memoized: this renders a large SVG tree (grid + every edge, label and node), +// so it must not re-reconcile when the parent page re-renders for unrelated +// reasons (chat busy-state, panel toggles). It only re-renders when its own +// props change. Keep parent-supplied handlers stable (useCallback) to preserve this. +export const OntologyGraph = memo(function OntologyGraph({ schemas, edges, selectedId, onSelect, onClear, selectedEdgeType }: Props) { const svgRef = useRef(null) const zoomRef = useRef>(null) const containerRef = useRef(null) @@ -659,4 +663,4 @@ export function OntologyGraph({ schemas, edges, selectedId, onSelect, onClear, s ) -} +}) diff --git a/src/app/admin/ontology/page.tsx b/src/app/admin/ontology/page.tsx index 05697f4..6b39e1d 100644 --- a/src/app/admin/ontology/page.tsx +++ b/src/app/admin/ontology/page.tsx @@ -77,6 +77,9 @@ export default function OntologyPage() { .map(([edgeType, count]) => ({ edgeType, count })) }, [store.edges, edgeSearch]) + // Stable so the memoized OntologyGraph doesn't re-render on unrelated page updates. + const handleClearSelection = useCallback(() => setSelectedId(null), []) + const handleSwitchToEdges = useCallback(() => { setSidebarTab("edges") setSelectedId(null) @@ -471,7 +474,7 @@ export default function OntologyPage() { edges={store.edges} selectedId={selectedId} onSelect={setSelectedId} - onClear={() => setSelectedId(null)} + onClear={handleClearSelection} selectedEdgeType={selectedEdgeType} /> )}