From 44ab6a5fc61f06e8bfcef5f6b073d8ed9b7fc0c2 Mon Sep 17 00:00:00 2001 From: Vorflux AI Date: Sun, 29 Mar 2026 01:12:22 +0000 Subject: [PATCH] fix: move version chain rebuild from useEffect to render path The chainIndex.rebuild() was called in a useEffect (runs after render), but getChain() was called in a useMemo (runs during render). This meant getChain() could read stale data from the old chain index when limitedDocuments changed. Moving rebuild() inline (during render) ensures the chain index is always up-to-date before getChain() is called. The rebuild() method has a referential equality guard that makes it a no-op on re-renders where limitedDocuments hasn't changed. --- packages/memory-graph/src/components/memory-graph.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/memory-graph/src/components/memory-graph.tsx b/packages/memory-graph/src/components/memory-graph.tsx index bdae2e8a..0602ce43 100644 --- a/packages/memory-graph/src/components/memory-graph.tsx +++ b/packages/memory-graph/src/components/memory-graph.tsx @@ -79,10 +79,11 @@ export function MemoryGraph({ colors, ) - // Rebuild version chain index when documents change - useEffect(() => { - chainIndex.current.rebuild(limitedDocuments) - }, [limitedDocuments]) + // Rebuild version chain index during render (not in an effect) so that + // the chain data is up-to-date when getChain() is called in useMemo below. + // rebuild() has an early-return guard (referential equality on documents) + // that makes this a no-op on re-renders where limitedDocuments hasn't changed. + chainIndex.current.rebuild(limitedDocuments) // Smart simulation re-init: track node ID set, only init() when IDs change const prevSimIdsRef = useRef("") @@ -494,6 +495,7 @@ export function MemoryGraph({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [activeNodeData, viewportVersion]) + // biome-ignore lint/correctness/useExhaustiveDependencies: limitedDocuments triggers re-computation after chainIndex.current.rebuild() runs with new data const activeVersionChain = useMemo(() => { if (!activeNodeData || activeNodeData.type !== "memory") return null return chainIndex.current.getChain(activeNodeData.id)