fix(apollo-react): improve stage node performance [MST-8122]#431
fix(apollo-react): improve stage node performance [MST-8122]#431SreedharAvvari wants to merge 1 commit intomainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Dependency License Review
License distribution
Excluded packages
|
There was a problem hiding this comment.
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
contextMenuItemsarrays with a lazygetContextMenuItems()API and compute menu items only when the menu opens. - Swap zoom reads from
useViewport()/prop drilling touseStoreApi().getState().transform[2]in StageNode/DraggableTask drag calculations. - Add a lightweight
useSetNodeSelectionhook 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
defaultPropsstill includes azoomproperty, butDraggableTaskPropsno longer defineszoom. This will fail TypeScript compilation for this test file; remove thezoomfield (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,
};
packages/apollo-react/src/canvas/components/StageNode/DraggableTask.test.tsx
Show resolved
Hide resolved
packages/apollo-react/src/canvas/components/StageNode/StageNode.tsx
Outdated
Show resolved
Hide resolved
54b7481 to
5dc911c
Compare
📦 Dev Packages
|
5dc911c to
2250ff5
Compare
packages/apollo-react/src/canvas/components/StageNode/DraggableTask.tsx
Outdated
Show resolved
Hide resolved
2250ff5 to
87653cf
Compare
87653cf to
f48fbe0
Compare
packages/apollo-react/src/canvas/components/StageNode/StageEdge.tsx
Outdated
Show resolved
Hide resolved
f48fbe0 to
b1c09c6
Compare
There was a problem hiding this comment.
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
buildContextMenuItemsunconditionally adds a divider after the "Replace task" item. IfonReplaceTaskFromToolboxis provided withoutonTaskGroupModification, 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());
packages/apollo-react/src/canvas/components/CanvasPerformance.stories.tsx
Outdated
Show resolved
Hide resolved
packages/apollo-react/src/canvas/components/StageNode/DraggableTask.test.tsx
Outdated
Show resolved
Hide resolved
b1c09c6 to
83fa391
Compare
packages/apollo-react/src/canvas/components/StageNode/StageNode.tsx
Outdated
Show resolved
Hide resolved
83fa391 to
71ec8d2
Compare
| }, []); | ||
|
|
||
| const handleGetContextMenuItems = useCallback(() => { | ||
| if (!getContextMenuItems || groupIndex === undefined || taskIndex === undefined) { |
There was a problem hiding this comment.
| if (!getContextMenuItems || groupIndex === undefined || taskIndex === undefined) { | |
| if (!getContextMenuItems || groupIndex == null || taskIndex == null) { |
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:
StageNode,StageNodeInner,StageEdge,StageTaskDragOverlay, andTaskMenuwithmemo()to prevent unnecessary re-rendersStageNodeComponentwrapper that destructures only stable props, stripping ReactFlow internal fields (positionAbsoluteX/Y,zIndex,isConnectable) soStageNodeInnerMemo's shallow comparison works effectivelystageEdgeGeometryEqualityselector to preventStageEdgere-renders when edge geometry hasn't changeduseSetNodeSelection()hook that provides onlysetSelectedNodeIdwithout subscribing to all nodesStageTaskDragOverlayas a separate memoized component rendered viacreatePortal()to isolate drag statebuildContextMenuItemsandhandleMenuItemClickinuseCallbackto stabilize referencesStageNodeBasePropstype separate from ReactFlow'sNodePropsfor cleaner prop boundariesnodeTypes/edgeTypes/defaultEdgeOptionsTesting
StageNode.test.tsxandDraggableTask.test.tsxto match new component signaturesCanvasPerformancestory: panning and dragging should remain smooth at 200 nodes