From 7fffd5153532cbabd8af64e86bb71b847941aea9 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Tue, 11 Aug 2026 15:36:21 +0800 Subject: [PATCH] fix(web): preserve workflow canvas after history updates (#40489) --- .../workflow/__tests__/index.spec.tsx | 44 ++++++++++++++++--- web/app/components/workflow/index.tsx | 3 -- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/web/app/components/workflow/__tests__/index.spec.tsx b/web/app/components/workflow/__tests__/index.spec.tsx index f7f0108be7a..3f5dc907e8c 100644 --- a/web/app/components/workflow/__tests__/index.spec.tsx +++ b/web/app/components/workflow/__tests__/index.spec.tsx @@ -1,9 +1,11 @@ import type { Edge, Node } from '../types' import { render, screen } from '@testing-library/react' +import userEvent from '@testing-library/user-event' import { useStoreApi } from 'reactflow' import { WorkflowContextProvider } from '../context' import { useDatasetsDetailStore } from '../datasets-detail-store/store' import WorkflowWithDefaultContext from '../index' +import { useStore } from '../store' import { BlockEnum } from '../types' import { useWorkflowHistoryStore } from '../workflow-history-store' @@ -37,15 +39,32 @@ const edges: Edge[] = [ const ContextConsumer = () => { const { store } = useWorkflowHistoryStore() + const historyNodeCount = useStore((state) => state.workflowHistory.nodes.length) const datasetCount = useDatasetsDetailStore((state) => Object.keys(state.datasetsDetail).length) const reactFlowStore = useStoreApi() + const advanceWorkflowHistory = () => { + const currentHistory = store.getState() + store.setState({ + ...currentHistory, + nodes: [ + ...currentHistory.nodes, + { + ...nodes[0]!, + id: 'node-next', + }, + ], + }) + } return ( -
- {`history:${store.getState().nodes.length}`} - {` datasets:${datasetCount}`} - {` reactflow:${String(!!reactFlowStore)}`} -
+ <> +
+ {`history:${historyNodeCount}`} + {` datasets:${datasetCount}`} + {` reactflow:${String(!!reactFlowStore)}`} +
+ + ) } @@ -61,4 +80,19 @@ describe('WorkflowWithDefaultContext', () => { expect(screen.getByText('history:1 datasets:0 reactflow:true')).toBeInTheDocument() }) + + it('keeps its children mounted when workflow history advances after initialization', async () => { + const user = userEvent.setup() + render( + + + + + , + ) + + await user.click(screen.getByRole('button', { name: 'Advance workflow history' })) + + expect(screen.getByText('history:2 datasets:0 reactflow:true')).toBeInTheDocument() + }) }) diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 18a06339f28..03fe0024d86 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -850,7 +850,6 @@ const WorkflowHistoryStoreInitializer = ({ children, }: WorkflowWithDefaultContextProps) => { const workflowStore = useWorkflowStore() - const workflowHistory = useStore((state) => state.workflowHistory) const [initialWorkflowHistory] = useState(() => ({ nodes, edges, @@ -866,8 +865,6 @@ const WorkflowHistoryStoreInitializer = ({ temporalStore.resume() }, [initialWorkflowHistory, workflowStore]) - if (workflowHistory !== initialWorkflowHistory) return null - return children }