refactor(react/svelte): use node lookup for perf improvement

This commit is contained in:
moklick
2023-11-13 16:43:57 +01:00
parent 6e1e702cf3
commit a147a20f6e
22 changed files with 127 additions and 78 deletions
@@ -30,6 +30,7 @@ export default function drag(domNode: Element, params: UseDragParams) {
return {
nodes: get(store.nodes),
nodesLookup: get(store.nodesLookup),
edges: get(store.edges),
nodeExtent: get(store.nodeExtent),
snapGrid: snapGrid ? snapGrid : [0, 0],
@@ -17,11 +17,18 @@
typeof ResizeObserver === 'undefined'
? null
: new ResizeObserver((entries: ResizeObserverEntry[]) => {
const updates = entries.map((entry: ResizeObserverEntry) => ({
id: entry.target.getAttribute('data-id') as string,
nodeElement: entry.target as HTMLDivElement,
forceUpdate: true
}));
const updates = new Map();
entries.forEach((entry: ResizeObserverEntry) => {
const id = entry.target.getAttribute('data-id') as string;
updates.set(id, {
id,
nodeElement: entry.target as HTMLDivElement,
forceUpdate: true
});
});
updateNodeDimensions(updates);
});
@@ -56,15 +56,15 @@ export function getDerivedConnectionProps(
currentConnection,
store.connectionLineType,
store.connectionMode,
store.nodes,
store.nodesLookup,
store.viewport
],
([connection, connectionLineType, connectionMode, nodes, viewport]) => {
([connection, connectionLineType, connectionMode, nodesLookup, viewport]) => {
if (!connection.connectionStartHandle?.nodeId) {
return initConnectionProps;
}
const fromNode = nodes.find((n) => n.id === connection.connectionStartHandle?.nodeId);
const fromNode = nodesLookup.get(connection.connectionStartHandle?.nodeId);
const fromHandleBounds = fromNode?.[internalsSymbol]?.handleBounds;
const handleBoundsStrict =
fromHandleBounds?.[connection.connectionStartHandle.type || 'source'] || [];
+9 -8
View File
@@ -9,17 +9,18 @@ export function getEdgeTree(store: SvelteFlowStoreState) {
[
store.edges,
store.nodes,
store.nodesLookup,
store.onlyRenderVisibleElements,
store.viewport,
store.width,
store.height
],
([edges, nodes, onlyRenderVisibleElements, viewport, width, height]) => {
([edges, , nodesLookup, onlyRenderVisibleElements, viewport, width, height]) => {
const visibleEdges =
onlyRenderVisibleElements && width && height
? edges.filter((edge) => {
const sourceNode = nodes.find((node) => node.id === edge.source);
const targetNode = nodes.find((node) => node.id === edge.target);
const sourceNode = nodesLookup.get(edge.source);
const targetNode = nodesLookup.get(edge.target);
return (
sourceNode &&
@@ -40,11 +41,11 @@ export function getEdgeTree(store: SvelteFlowStoreState) {
);
return derived(
[visibleEdges, store.nodes, store.connectionMode, store.onError],
([visibleEdges, nodes, connectionMode, onError]) => {
[visibleEdges, store.nodes, store.nodesLookup, store.connectionMode, store.onError],
([visibleEdges, , nodesLookup, connectionMode, onError]) => {
const layoutedEdges = visibleEdges.reduce<EdgeLayouted[]>((res, edge) => {
const sourceNode = nodes.find((node) => node.id === edge.source);
const targetNode = nodes.find((node) => node.id === edge.target);
const sourceNode = nodesLookup.get(edge.source);
const targetNode = nodesLookup.get(edge.target);
if (!sourceNode || !targetNode) {
return res;
@@ -70,7 +71,7 @@ export function getEdgeTree(store: SvelteFlowStoreState) {
return res;
}, []);
const groupedEdges = groupEdgesByZLevel<EdgeLayouted>(layoutedEdges, nodes, false);
const groupedEdges = groupEdgesByZLevel<EdgeLayouted>(layoutedEdges, nodesLookup, false);
return groupedEdges;
}
+2 -1
View File
@@ -86,10 +86,11 @@ export function createStore({
});
};
function updateNodeDimensions(updates: NodeDimensionUpdate[]) {
function updateNodeDimensions(updates: Map<string, NodeDimensionUpdate>) {
const nextNodes = updateNodeDimensionsSystem(
updates,
get(store.nodes),
get(store.nodesLookup),
get(store.domNode),
get(store.nodeOrigin)
);
@@ -59,7 +59,11 @@ export const getInitialStore = ({
height?: number;
fitView?: boolean;
}) => {
const nextNodes = updateNodes(nodes, [], { nodeOrigin: [0, 0], elevateNodesOnSelect: false });
const nodesLookup = new Map<string, Node>();
const nextNodes = updateNodes(nodes, nodesLookup, {
nodeOrigin: [0, 0],
elevateNodesOnSelect: false
});
let viewport: Viewport = { x: 0, y: 0, zoom: 1 };
@@ -75,7 +79,8 @@ export const getInitialStore = ({
return {
flowId: writable<string | null>(null),
nodes: createNodesStore(nextNodes),
nodes: createNodesStore(nextNodes, nodesLookup),
nodesLookup: readable<Map<string, Node>>(nodesLookup),
visibleNodes: readable<Node[]>([]),
edges: createEdgesStore(edges),
edgeTree: readable<GroupedEdges<EdgeLayouted>[]>([]),
+1 -1
View File
@@ -27,7 +27,7 @@ export type SvelteFlowStoreActions = {
setTranslateExtent: (extent: CoordinateExtent) => void;
fitView: (options?: FitViewOptions) => boolean;
updateNodePositions: UpdateNodePositions;
updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void;
updateNodeDimensions: (updates: Map<string, NodeDimensionUpdate>) => void;
unselectNodesAndEdges: (params?: { nodes?: Node[]; edges?: Edge[] }) => void;
addSelectedNodes: (ids: string[]) => void;
addSelectedEdges: (ids: string[]) => void;
+3 -2
View File
@@ -111,7 +111,8 @@ export type NodeStoreOptions = {
// we are creating a custom store for the internals nodes in order to update the zIndex and positionAbsolute.
// The user only passes in relative positions, so we need to calculate the absolute positions based on the parent nodes.
export const createNodesStore = (
nodes: Node[]
nodes: Node[],
nodesLookup: Map<string, Node>
): {
subscribe: (this: void, run: Subscriber<Node[]>) => Unsubscriber;
update: (this: void, updater: Updater<Node[]>) => void;
@@ -125,7 +126,7 @@ export const createNodesStore = (
let elevateNodesOnSelect = true;
const _set = (nds: Node[]): Node[] => {
const nextNodes = updateNodes(nds, value, {
const nextNodes = updateNodes(nds, nodesLookup, {
elevateNodesOnSelect,
defaults
});