feat(useReactFlow): add updateEdge and updateEdgeData (#4351)
* feat(useReactFlow): add updateEdge and updateEdgeData * chore(examples): add updateEdge call
This commit is contained in:
@@ -28,10 +28,15 @@ for (let i = 0; i < 100; i++) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const initEdges: Edge[] = [];
|
const initEdges: Edge[] = initNodes.reduce<Edge[]>((res, node, index) => {
|
||||||
|
if (index > 0) {
|
||||||
|
res.push({ id: `${index - 1}-${index}`, source: (index - 1).toString(), target: index.toString() });
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}, []);
|
||||||
|
|
||||||
const CustomNodeFlow = () => {
|
const CustomNodeFlow = () => {
|
||||||
const { setNodes, updateNodeData } = useReactFlow();
|
const { setNodes, updateNodeData, updateEdge } = useReactFlow();
|
||||||
const [nodes, , onNodesChange] = useNodesState(initNodes);
|
const [nodes, , onNodesChange] = useNodesState(initNodes);
|
||||||
const [edges, setEdges, onEdgesChange] = useEdgesState(initEdges);
|
const [edges, setEdges, onEdgesChange] = useEdgesState(initEdges);
|
||||||
|
|
||||||
@@ -55,6 +60,10 @@ const CustomNodeFlow = () => {
|
|||||||
nodes.forEach((node) => updateNodeData(node.id, { label: 'node update' }));
|
nodes.forEach((node) => updateNodeData(node.id, { label: 'node update' }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const multiUpdateEdges = () => {
|
||||||
|
edges.forEach((edge) => updateEdge(edge.id, { label: 'edge update' }));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
@@ -70,6 +79,7 @@ const CustomNodeFlow = () => {
|
|||||||
<Panel>
|
<Panel>
|
||||||
<button onClick={multiSetNodes}>set nodes</button>
|
<button onClick={multiSetNodes}>set nodes</button>
|
||||||
<button onClick={multiUpdateNodes}>update nodes</button>
|
<button onClick={multiUpdateNodes}>update nodes</button>
|
||||||
|
<button onClick={multiUpdateEdges}>update edges</button>
|
||||||
</Panel>
|
</Panel>
|
||||||
</ReactFlow>
|
</ReactFlow>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
import useViewportHelper from './useViewportHelper';
|
import useViewportHelper from './useViewportHelper';
|
||||||
import { useStore, useStoreApi } from './useStore';
|
import { useStore, useStoreApi } from './useStore';
|
||||||
import { useBatchContext } from '../components/BatchProvider';
|
import { useBatchContext } from '../components/BatchProvider';
|
||||||
import { elementToRemoveChange, isNode } from '../utils';
|
import { elementToRemoveChange, isEdge, isNode } from '../utils';
|
||||||
import type { ReactFlowInstance, Node, Edge, InternalNode, ReactFlowState, GeneralHelpers } from '../types';
|
import type { ReactFlowInstance, Node, Edge, InternalNode, ReactFlowState, GeneralHelpers } from '../types';
|
||||||
|
|
||||||
const selector = (s: ReactFlowState) => !!s.panZoom;
|
const selector = (s: ReactFlowState) => !!s.panZoom;
|
||||||
@@ -41,6 +41,10 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
|||||||
batchContext.nodeQueue.push(payload as NodeType[]);
|
batchContext.nodeQueue.push(payload as NodeType[]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setEdges: GeneralHelpers<NodeType, EdgeType>['setEdges'] = (payload) => {
|
||||||
|
batchContext.edgeQueue.push(payload as EdgeType[]);
|
||||||
|
};
|
||||||
|
|
||||||
const getNodeRect = (node: NodeType | { id: string }): Rect | null => {
|
const getNodeRect = (node: NodeType | { id: string }): Rect | null => {
|
||||||
const { nodeLookup, nodeOrigin } = store.getState();
|
const { nodeLookup, nodeOrigin } = store.getState();
|
||||||
|
|
||||||
@@ -77,6 +81,23 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateEdge: GeneralHelpers<NodeType, EdgeType>['updateEdge'] = (
|
||||||
|
id,
|
||||||
|
edgeUpdate,
|
||||||
|
options = { replace: false }
|
||||||
|
) => {
|
||||||
|
setEdges((prevEdges) =>
|
||||||
|
prevEdges.map((edge) => {
|
||||||
|
if (edge.id === id) {
|
||||||
|
const nextEdge = typeof edgeUpdate === 'function' ? edgeUpdate(edge as EdgeType) : edgeUpdate;
|
||||||
|
return options.replace && isEdge(nextEdge) ? (nextEdge as EdgeType) : { ...edge, ...nextEdge };
|
||||||
|
}
|
||||||
|
|
||||||
|
return edge;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getNodes: () => store.getState().nodes.map((n) => ({ ...n })) as NodeType[],
|
getNodes: () => store.getState().nodes.map((n) => ({ ...n })) as NodeType[],
|
||||||
getNode: (id) => getInternalNode(id)?.internals.userNode as NodeType,
|
getNode: (id) => getInternalNode(id)?.internals.userNode as NodeType,
|
||||||
@@ -87,9 +108,7 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
|||||||
},
|
},
|
||||||
getEdge: (id) => store.getState().edgeLookup.get(id) as EdgeType,
|
getEdge: (id) => store.getState().edgeLookup.get(id) as EdgeType,
|
||||||
setNodes,
|
setNodes,
|
||||||
setEdges: (payload) => {
|
setEdges,
|
||||||
batchContext.edgeQueue.push(payload as EdgeType[]);
|
|
||||||
},
|
|
||||||
addNodes: (payload) => {
|
addNodes: (payload) => {
|
||||||
const newNodes = Array.isArray(payload) ? payload : [payload];
|
const newNodes = Array.isArray(payload) ? payload : [payload];
|
||||||
batchContext.nodeQueue.push((nodes) => [...nodes, ...newNodes]);
|
batchContext.nodeQueue.push((nodes) => [...nodes, ...newNodes]);
|
||||||
@@ -200,6 +219,17 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
|||||||
options
|
options
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
updateEdge,
|
||||||
|
updateEdgeData: (id, dataUpdate, options = { replace: false }) => {
|
||||||
|
updateEdge(
|
||||||
|
id,
|
||||||
|
(edge) => {
|
||||||
|
const nextData = typeof dataUpdate === 'function' ? dataUpdate(edge) : dataUpdate;
|
||||||
|
return options.replace ? { ...edge, data: nextData } : { ...edge, data: { ...edge.data, ...nextData } };
|
||||||
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -143,6 +143,36 @@ export type GeneralHelpers<NodeType extends Node = Node, EdgeType extends Edge =
|
|||||||
dataUpdate: Partial<NodeType['data']> | ((node: NodeType) => Partial<NodeType['data']>),
|
dataUpdate: Partial<NodeType['data']> | ((node: NodeType) => Partial<NodeType['data']>),
|
||||||
options?: { replace: boolean }
|
options?: { replace: boolean }
|
||||||
) => void;
|
) => void;
|
||||||
|
/**
|
||||||
|
* Updates an edge.
|
||||||
|
*
|
||||||
|
* @param id - id of the edge to update
|
||||||
|
* @param edgeUpdate - the edge update as an object or a function that receives the current edge and returns the edge update
|
||||||
|
* @param options.replace - if true, the edge is replaced with the edge update, otherwise the changes get merged
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* updateEdge('edge-1', (edge) => ({ label: 'A new label' }));
|
||||||
|
*/
|
||||||
|
updateEdge: (
|
||||||
|
id: string,
|
||||||
|
edgeUpdate: Partial<EdgeType> | ((edge: EdgeType) => Partial<EdgeType>),
|
||||||
|
options?: { replace: boolean }
|
||||||
|
) => void;
|
||||||
|
/**
|
||||||
|
* Updates the data attribute of a edge.
|
||||||
|
*
|
||||||
|
* @param id - id of the edge to update
|
||||||
|
* @param dataUpdate - the data update as an object or a function that receives the current data and returns the data update
|
||||||
|
* @param options.replace - if true, the data is replaced with the data update, otherwise the changes get merged
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* updateEdgeData('edge-1', { label: 'A new label' });
|
||||||
|
*/
|
||||||
|
updateEdgeData: (
|
||||||
|
id: string,
|
||||||
|
dataUpdate: Partial<EdgeType['data']> | ((edge: EdgeType) => Partial<EdgeType['data']>),
|
||||||
|
options?: { replace: boolean }
|
||||||
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ReactFlowInstance<NodeType extends Node = Node, EdgeType extends Edge = Edge> = GeneralHelpers<
|
export type ReactFlowInstance<NodeType extends Node = Node, EdgeType extends Edge = Edge> = GeneralHelpers<
|
||||||
|
|||||||
Reference in New Issue
Block a user