From 82f0b98fca4f67bc63fd6c9764a4dccfef570593 Mon Sep 17 00:00:00 2001 From: Jonathan Dobson Date: Sat, 16 Aug 2025 12:21:26 -0400 Subject: [PATCH] =?UTF-8?q?react-flow=20updates:=20allow=20one=20in=20curr?= =?UTF-8?q?ent=20render=20cycle;=20defer=20rest=20to=20=E2=80=A6=20(#3213)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/routes/workflows/editor/FlowRenderer.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx b/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx index 9c6674ef..f787457a 100644 --- a/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx +++ b/skyvern-frontend/src/routes/workflows/editor/FlowRenderer.tsx @@ -79,6 +79,8 @@ import { } from "./workflowEditorUtils"; import { useAutoPan } from "./useAutoPan"; +const nextTick = () => new Promise((resolve) => setTimeout(resolve, 0)); + function convertToParametersYAML( parameters: ParametersState, ): Array< @@ -619,13 +621,20 @@ function FlowRenderer({ ) { workflowChangesStore.setHasChanges(true); } - // defer update to next tick to prevent max recursion errors; - // NOTE: deferring too long causes node updates to be skipped + + // only allow one update in _this_ render cycle if (onNodesChangeTimeoutRef.current === null) { onNodesChange(changes); onNodesChangeTimeoutRef.current = setTimeout(() => { onNodesChangeTimeoutRef.current = null; }, 0); + } else { + // if we have an update in this render cycle already, then to + // prevent max recursion errors, defer the update to next render + // cycle + nextTick().then(() => { + onNodesChange(changes); + }); } }} onEdgesChange={onEdgesChange}