diff --git a/examples/react/src/examples/UseNodesInit/index.tsx b/examples/react/src/examples/UseNodesInit/index.tsx
index 549315ca..d4932ae1 100644
--- a/examples/react/src/examples/UseNodesInit/index.tsx
+++ b/examples/react/src/examples/UseNodesInit/index.tsx
@@ -11,6 +11,8 @@ import {
useEdgesState,
OnConnect,
useNodesInitialized,
+ Panel,
+ useReactFlow,
} from '@xyflow/react';
const initialNodes: Node[] = [
@@ -49,6 +51,7 @@ const initialEdges: Edge[] = [
];
const UseZoomPanHelperFlow = () => {
+ const { addNodes } = useReactFlow();
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
@@ -59,6 +62,13 @@ const UseZoomPanHelperFlow = () => {
console.log('initialized', initialized);
}, [initialized]);
+ const addNode = () =>
+ addNodes({
+ id: `${Math.random()}`,
+ data: { label: 'new node' },
+ position: { x: Math.random() * 400, y: Math.random() * 400 },
+ });
+
return (
{
>
+
+
+
);
};
diff --git a/packages/react/src/hooks/useReactFlow.ts b/packages/react/src/hooks/useReactFlow.ts
index 4ac0e50c..a61d4907 100644
--- a/packages/react/src/hooks/useReactFlow.ts
+++ b/packages/react/src/hooks/useReactFlow.ts
@@ -1,9 +1,11 @@
import { useCallback, useMemo } from 'react';
import {
+ EdgeRemoveChange,
evaluateAbsolutePosition,
getElementsToRemove,
getOverlappingArea,
isRectObject,
+ NodeRemoveChange,
nodeToRect,
type Rect,
} from '@xyflow/system';
@@ -11,7 +13,7 @@ import {
import useViewportHelper from './useViewportHelper';
import { useStoreApi } from './useStore';
import { useBatchContext } from '../components/BatchProvider';
-import { isNode } from '../utils';
+import { elementToRemoveChange, isNode } from '../utils';
import type { ReactFlowInstance, Instance, Node, Edge, InternalNode } from '../types';
/**
@@ -87,12 +89,10 @@ export function useReactFlow 0;
if (hasMatchingEdges) {
- if (hasDefaultEdges) {
- const nextEdges = edges.filter((e) => !matchingEdges.some((mE) => mE.id === e.id));
- store.getState().setEdges(nextEdges);
- }
+ const edgeChanges: EdgeRemoveChange[] = matchingEdges.map(elementToRemoveChange);
onEdgesDelete?.(matchingEdges);
- onEdgesChange?.(
- matchingEdges.map((edge) => ({
- id: edge.id,
- type: 'remove',
- }))
- );
+ triggerEdgeChanges(edgeChanges);
}
if (hasMatchingNodes) {
- if (hasDefaultNodes) {
- const nextNodes = nodes.filter((n) => !matchingNodes.some((mN) => mN.id === n.id));
- store.getState().setNodes(nextNodes);
- }
+ const nodeChanges: NodeRemoveChange[] = matchingNodes.map(elementToRemoveChange);
onNodesDelete?.(matchingNodes);
- onNodesChange?.(matchingNodes.map((node) => ({ id: node.id, type: 'remove' })));
+ triggerNodeChanges(nodeChanges);
}
if (hasMatchingNodes || hasMatchingEdges) {
diff --git a/packages/react/src/store/index.ts b/packages/react/src/store/index.ts
index 5d7f521b..29f99999 100644
--- a/packages/react/src/store/index.ts
+++ b/packages/react/src/store/index.ts
@@ -74,7 +74,7 @@ const createStore = ({
// new dimensions and update the nodes.
updateNodeInternals: (updates) => {
const {
- onNodesChange,
+ triggerNodeChanges,
fitView,
nodeLookup,
parentLookup,
@@ -120,7 +120,7 @@ const createStore = ({
if (debug) {
console.log('React Flow: trigger node changes', changes);
}
- onNodesChange?.(changes);
+ triggerNodeChanges?.(changes);
}
},
updateNodePositions: (nodeDragItems, dragging = false) => {
diff --git a/packages/react/src/utils/changes.ts b/packages/react/src/utils/changes.ts
index cdc83088..df215340 100644
--- a/packages/react/src/utils/changes.ts
+++ b/packages/react/src/utils/changes.ts
@@ -6,6 +6,8 @@ import {
NodeChange,
NodeSelectionChange,
EdgeSelectionChange,
+ NodeRemoveChange,
+ EdgeRemoveChange,
} from '@xyflow/system';
import type { Node, Edge, InternalNode } from '../types';
@@ -258,3 +260,10 @@ export function getElementsDiffChanges({
return changes;
}
+
+export function elementToRemoveChange(item: T): NodeRemoveChange | EdgeRemoveChange {
+ return {
+ id: item.id,
+ type: 'remove',
+ };
+}
diff --git a/packages/system/src/utils/graph.ts b/packages/system/src/utils/graph.ts
index 53592609..6a4715b8 100644
--- a/packages/system/src/utils/graph.ts
+++ b/packages/system/src/utils/graph.ts
@@ -395,7 +395,7 @@ export async function getElementsToRemove {
- const nodeIds = nodesToRemove.map((node) => node.id);
+ const nodeIds = new Set(nodesToRemove.map((node) => node.id));
const matchingNodes: NodeType[] = [];
for (const node of nodes) {
@@ -403,7 +403,7 @@ export async function getElementsToRemove n.id === node.parentId);
if (isIncluded || parentHit) {
@@ -411,13 +411,13 @@ export async function getElementsToRemove edge.id);
+ const edgeIds = new Set(edgesToRemove.map((edge) => edge.id));
const deletableEdges = edges.filter((edge) => edge.deletable !== false);
const connectedEdges = getConnectedEdges(matchingNodes, deletableEdges);
const matchingEdges: EdgeType[] = connectedEdges;
for (const edge of deletableEdges) {
- const isIncluded = edgeIds.includes(edge.id);
+ const isIncluded = edgeIds.has(edge.id);
if (isIncluded && !matchingEdges.find((e) => e.id === edge.id)) {
matchingEdges.push(edge);