From 0b48a7e991b9ab71518b0f7a7cded4f1bbc702ca Mon Sep 17 00:00:00 2001 From: Joel Date: Tue, 19 May 2026 20:29:16 +0800 Subject: [PATCH] fix: workflow node selection state not sync caused problem (#36390) --- .../__tests__/use-nodes-interactions.spec.ts | 45 +++++++++++++++++++ .../workflow/hooks/use-nodes-interactions.ts | 10 ++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/web/app/components/workflow/hooks/__tests__/use-nodes-interactions.spec.ts b/web/app/components/workflow/hooks/__tests__/use-nodes-interactions.spec.ts index a77606fefc..ec961c3530 100644 --- a/web/app/components/workflow/hooks/__tests__/use-nodes-interactions.spec.ts +++ b/web/app/components/workflow/hooks/__tests__/use-nodes-interactions.spec.ts @@ -484,6 +484,51 @@ describe('useNodesInteractions', () => { expect(nodesArg[0]?.data.selected).toBe(false) }) + it('keeps ReactFlow and node data selection in sync when selecting another node', () => { + currentNodes = [ + createNode({ + id: 'knowledge-retrieval-node', + selected: true, + data: { + type: BlockEnum.KnowledgeRetrieval, + title: 'Knowledge Retrieval', + desc: '', + selected: true, + }, + }), + createNode({ + id: 'answer-node', + position: { x: 100, y: 0 }, + data: { + type: BlockEnum.Answer, + title: 'Answer', + desc: '', + }, + }), + ] + rfState.nodes = currentNodes as unknown as typeof rfState.nodes + + const { result } = renderWorkflowHook(() => useNodesInteractions(), { + historyStore: { + nodes: currentNodes, + edges: currentEdges, + }, + }) + + act(() => { + result.current.handleNodeSelect('answer-node') + }) + + const nodesArg = rfState.setNodes.mock.calls[0]?.[0] as Node[] + const knowledgeNode = nodesArg.find(node => node.id === 'knowledge-retrieval-node') + const answerNode = nodesArg.find(node => node.id === 'answer-node') + + expect(knowledgeNode?.selected).toBe(false) + expect(knowledgeNode?.data.selected).toBe(false) + expect(answerNode?.selected).toBe(true) + expect(answerNode?.data.selected).toBe(true) + }) + it('skips clipboard copy when bundled/selected nodes have no metadata', () => { currentNodes = [ createNode({ diff --git a/web/app/components/workflow/hooks/use-nodes-interactions.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts index 934bbff8bf..fcf7fe9714 100644 --- a/web/app/components/workflow/hooks/use-nodes-interactions.ts +++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts @@ -440,16 +440,12 @@ export const useNodesInteractions = () => { if (initShowLastRunTab) workflowStore.setState({ initShowLastRunTab: true }) const { nodes, setNodes, edges, setEdges } = collaborativeWorkflow.getState() - const selectedNode = nodes.find(node => node.data.selected) - - if (!cancelSelection && selectedNode?.id === nodeId) - return const newNodes = produce(nodes, (draft) => { draft.forEach((node) => { - if (node.id === nodeId) - node.data.selected = !cancelSelection - else node.data.selected = false + const selected = node.id === nodeId && !cancelSelection + node.selected = selected + node.data.selected = selected }) }) setNodes(newNodes, false)