diff --git a/frontend/src/components/tree-editor/TreeCanvasNode.tsx b/frontend/src/components/tree-editor/TreeCanvasNode.tsx index 66f83233..3a3cb005 100644 --- a/frontend/src/components/tree-editor/TreeCanvasNode.tsx +++ b/frontend/src/components/tree-editor/TreeCanvasNode.tsx @@ -1,4 +1,4 @@ -import { useState, useCallback } from 'react' +import { useState, useCallback, useEffect } from 'react' import { HelpCircle, Zap, @@ -97,13 +97,22 @@ export function TreeCanvasNode({ cloneNodeWithoutChildren(node) ) - // Reset draft if node changes while editing (e.g. store update from undo) + // Reset draft if node ID changes (e.g. navigating between nodes) const [lastNodeId, setLastNodeId] = useState(node.id) if (node.id !== lastNodeId) { setDraft(cloneNodeWithoutChildren(node)) setLastNodeId(node.id) } + // Re-sync draft from store whenever the card is opened, so stale next_node_id + // values (written back after stub creation) don't cause duplicate stubs on re-save + useEffect(() => { + if (isExpanded) { + setDraft(cloneNodeWithoutChildren(node)) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [isExpanded]) + const handleDraftUpdate = useCallback((updates: Partial) => { setDraft((prev) => ({ ...prev, ...updates })) }, [])