Skip to content

fix(apollo-react): improve stage node performance [MST-8122]#431

Open
SreedharAvvari wants to merge 1 commit intomainfrom
fix/stage-node-perf
Open

fix(apollo-react): improve stage node performance [MST-8122]#431
SreedharAvvari wants to merge 1 commit intomainfrom
fix/stage-node-perf

Conversation

@SreedharAvvari
Copy link
Copy Markdown
Contributor

@SreedharAvvari SreedharAvvari commented Mar 31, 2026

Description

Improve StageNode rendering performance at scale by reducing unnecessary re-renders across the component tree.

Also added new CanvasPerformance story with configurable stage count (1-200) for benchmarking render performance.

Key changes:

  • Wrap StageNode, StageNodeInner, StageEdge, StageTaskDragOverlay, and TaskMenu with memo() to prevent unnecessary re-renders
  • Add StageNodeComponent wrapper that destructures only stable props, stripping ReactFlow internal fields (positionAbsoluteX/Y, zIndex, isConnectable) so StageNodeInnerMemo's shallow comparison works effectively
  • Add custom stageEdgeGeometryEquality selector to prevent StageEdge re-renders when edge geometry hasn't changed
  • Introduce lightweight useSetNodeSelection() hook that provides only setSelectedNodeId without subscribing to all nodes
  • Extract StageTaskDragOverlay as a separate memoized component rendered via createPortal() to isolate drag state
  • Wrap buildContextMenuItems and handleMenuItemClick in useCallback to stabilize references
  • Extract StageNodeBaseProps type separate from ReactFlow's NodeProps for cleaner prop boundaries
  • Stories also updated to use memoized nodeTypes/edgeTypes/defaultEdgeOptions

Testing

  • All 1274 existing tests pass (65 test files)
  • Updated StageNode.test.tsx and DraggableTask.test.tsx to match new component signatures
  • Verify with CanvasPerformance story: panning and dragging should remain smooth at 200 nodes

Copilot AI review requested due to automatic review settings March 31, 2026 18:09
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 31, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (PT)
apollo-canvas 🟢 Ready Preview, Logs Apr 01, 2026, 06:49:52 AM
apollo-landing 🟢 Ready Preview, Logs Apr 01, 2026, 06:47:19 AM
apollo-ui-react 🟢 Ready Preview, Logs Apr 01, 2026, 06:48:52 AM
apollo-vertex 🟢 Ready Preview, Logs Apr 01, 2026, 06:48:39 AM
apollo-wind 🟢 Ready Preview, Logs Apr 01, 2026, 06:47:17 AM

@github-actions github-actions bot added the size:XL 500-999 changed lines. label Mar 31, 2026
@github-actions
Copy link
Copy Markdown

Dependency License Review

  • 1924 package(s) scanned
  • ✅ No license issues found
  • ⚠️ 3 package(s) excluded (see details below)
License distribution
License Packages
MIT 1689
ISC 89
Apache-2.0 56
BSD-3-Clause 28
BSD-2-Clause 23
BlueOak-1.0.0 8
MPL-2.0 5
MIT OR Apache-2.0 3
MIT-0 3
CC0-1.0 3
LGPL-3.0-or-later 2
(MIT OR Apache-2.0) 2
Unlicense 2
Python-2.0 1
CC-BY-4.0 1
(MPL-2.0 OR Apache-2.0) 1
Unknown 1
Artistic-2.0 1
(WTFPL OR MIT) 1
(BSD-2-Clause OR MIT OR Apache-2.0) 1
CC-BY-3.0 1
0BSD 1
(MIT OR CC0-1.0) 1
MIT AND ISC 1
Excluded packages
Package Version License Reason
@img/sharp-libvips-linux-x64 1.2.4 LGPL-3.0-or-later LGPL pre-built binary, not linked
@img/sharp-libvips-linuxmusl-x64 1.2.4 LGPL-3.0-or-later LGPL pre-built binary, not linked
khroma 2.1.0 Unknown MIT per GitHub repo, missing license field in package.json

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets performance improvements in the canvas StageNode/DraggableTask area by reducing per-render work (lazy-building context menu items) and avoiding broader React Flow subscriptions (switching from useViewport to useStoreApi/store access patterns).

Changes:

  • Replace eager contextMenuItems arrays with a lazy getContextMenuItems() API and compute menu items only when the menu opens.
  • Swap zoom reads from useViewport()/prop drilling to useStoreApi().getState().transform[2] in StageNode/DraggableTask drag calculations.
  • Add a lightweight useSetNodeSelection hook and optimize node selection updates to avoid unnecessary node object churn.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/apollo-react/src/canvas/components/StageNode/TaskMenu.tsx Lazily builds and stores transformed menu items on menu open via getContextMenuItems().
packages/apollo-react/src/canvas/components/StageNode/StageNode.tsx Removes useViewport subscription, uses store API for zoom, and switches to lazy context menu item building.
packages/apollo-react/src/canvas/components/StageNode/StageNode.test.tsx Updates tests/mocks to align with lazy menu building and revised selection hook usage.
packages/apollo-react/src/canvas/components/StageNode/StageNode.stories.tsx Refactors story decorators/wrappers to reduce re-creation and inject handlers more efficiently.
packages/apollo-react/src/canvas/components/StageNode/DraggableTask.types.ts Updates task API to getContextMenuItems and removes zoom prop.
packages/apollo-react/src/canvas/components/StageNode/DraggableTask.tsx Uses store API zoom for drag transform scaling and consumes getContextMenuItems.
packages/apollo-react/src/canvas/components/StageNode/DraggableTask.test.tsx Updates tests to use getContextMenuItems (but currently has issues noted in comments).
packages/apollo-react/src/canvas/components/NodePropertiesPanel/hooks/useNodeSelection.ts Optimizes selection mapping and introduces useSetNodeSelection.
packages/apollo-react/src/canvas/components/NodePropertiesPanel/hooks/index.ts Exports the new useSetNodeSelection hook.
Comments suppressed due to low confidence (1)

packages/apollo-react/src/canvas/components/StageNode/DraggableTask.test.tsx:54

  • defaultProps still includes a zoom property, but DraggableTaskProps no longer defines zoom. This will fail TypeScript compilation for this test file; remove the zoom field (or reintroduce the prop if it’s still required).
const defaultProps: DraggableTaskProps = {
  task: createTask('task-1', 'Test Task'),
  taskExecution: undefined,
  isSelected: false,
  isParallel: false,
  onTaskClick: vi.fn(),
  isDragDisabled: false,
  zoom: 1,
};

@SreedharAvvari SreedharAvvari added the dev-packages Adds dev package publishing on pushes to this PR label Apr 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

📦 Dev Packages

Package Status Updated (PT)
@uipath/apollo-react@3.63.0-pr431.16bbfa4 🟢 Published Apr 01, 2026, 06:49:43 AM

Copilot AI review requested due to automatic review settings April 1, 2026 04:49
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

@github-actions github-actions bot added size:XXL 1,000+ changed lines. and removed size:XL 500-999 changed lines. labels Apr 1, 2026
@SreedharAvvari SreedharAvvari requested a review from Copilot April 1, 2026 10:10
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

packages/apollo-react/src/canvas/components/StageNode/StageNode.tsx:300

  • buildContextMenuItems unconditionally adds a divider after the "Replace task" item. If onReplaceTaskFromToolbox is provided without onTaskGroupModification, the menu will end with a trailing separator. Consider only adding the divider when additional items will follow.
            if (taskId) onTaskClick?.(taskId);
            setIsReplacingTask(true);
          })
        );
        items.push(getDivider());

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

}, []);

const handleGetContextMenuItems = useCallback(() => {
if (!getContextMenuItems || groupIndex === undefined || taskIndex === undefined) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!getContextMenuItems || groupIndex === undefined || taskIndex === undefined) {
if (!getContextMenuItems || groupIndex == null || taskIndex == null) {

@SreedharAvvari SreedharAvvari changed the title fix(apollo-react): improve stage node performance fix(apollo-react): improve stage node performance [MST-8122] Apr 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dev-packages Adds dev package publishing on pushes to this PR size:XXL 1,000+ changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants