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
@@ -65,8 +65,8 @@ function ResizeControl({
const dragHandler = drag<HTMLDivElement, unknown>()
.on('start', (event: ResizeDragEvent) => {
const { nodes, transform, snapGrid, snapToGrid } = store.getState();
const node = nodes.find((n) => n.id === id);
const { nodesLookup, transform, snapGrid, snapToGrid } = store.getState();
const node = nodesLookup.get(id);
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
prevValues.current = {
@@ -86,9 +86,9 @@ function ResizeControl({
onResizeStart?.(event, { ...prevValues.current });
})
.on('drag', (event: ResizeDragEvent) => {
const { nodes, transform, snapGrid, snapToGrid, triggerNodeChanges } = store.getState();
const { nodesLookup, transform, snapGrid, snapToGrid, triggerNodeChanges } = store.getState();
const { xSnapped, ySnapped } = getPointerPosition(event.sourceEvent, { transform, snapGrid, snapToGrid });
const node = nodes.find((n) => n.id === id);
const node = nodesLookup.get(id);
if (node) {
const changes: NodeChange[] = [];
@@ -43,7 +43,7 @@ const ConnectionLine = ({
const { fromNode, handleId, toX, toY, connectionMode } = useStore(
useCallback(
(s: ReactFlowStore) => ({
fromNode: s.nodes.find((n) => n.id === nodeId),
fromNode: s.nodesLookup.get(nodeId),
handleId: s.connectionStartHandle?.handleId,
toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
@@ -53,9 +53,9 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
const [updateHover, setUpdateHover] = useState<boolean>(false);
const [updating, setUpdating] = useState<boolean>(false);
const store = useStoreApi();
const edgePosition = useStore((state) => {
const sourceNode = state.nodes.find((n) => n.id === source);
const targetNode = state.nodes.find((n) => n.id === target);
const edgePosition = useStore(function edgeSelector(state) {
const sourceNode = state.nodesLookup.get(source);
const targetNode = state.nodesLookup.get(target);
if (!sourceNode || !targetNode) {
return null;
@@ -48,11 +48,16 @@ const NodeRenderer = (props: NodeRendererProps) => {
}
const observer = 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);
});
+3 -3
View File
@@ -12,8 +12,8 @@ function useVisibleEdges(onlyRenderVisible: boolean, elevateEdgesOnSelect: boole
const visibleEdges =
onlyRenderVisible && s.width && s.height
? s.edges.filter((e) => {
const sourceNode = s.nodes.find((n) => n.id === e.source);
const targetNode = s.nodes.find((n) => n.id === e.target);
const sourceNode = s.nodesLookup.get(e.source);
const targetNode = s.nodesLookup.get(e.target);
return (
sourceNode &&
@@ -29,7 +29,7 @@ function useVisibleEdges(onlyRenderVisible: boolean, elevateEdgesOnSelect: boole
})
: s.edges;
return groupEdgesByZLevel(visibleEdges, s.nodes, elevateEdgesOnSelect);
return groupEdgesByZLevel(visibleEdges, s.nodesLookup, elevateEdgesOnSelect);
},
[onlyRenderVisible, elevateEdgesOnSelect]
),
+18 -8
View File
@@ -41,8 +41,8 @@ const createRFStore = ({
(set, get) => ({
...getInitialState({ nodes, edges, width, height, fitView }),
setNodes: (nodes: Node[]) => {
const { nodes: storeNodes, nodeOrigin, elevateNodesOnSelect } = get();
const nextNodes = updateNodes(nodes, storeNodes, { nodeOrigin, elevateNodesOnSelect });
const { nodesLookup, nodeOrigin, elevateNodesOnSelect } = get();
const nextNodes = updateNodes(nodes, nodesLookup, { nodeOrigin, elevateNodesOnSelect });
set({ nodes: nextNodes });
},
@@ -68,7 +68,7 @@ const createRFStore = ({
};
if (hasDefaultNodes) {
nextState.nodes = updateNodes(nodes, [], {
nextState.nodes = updateNodes(nodes, new Map(), {
nodeOrigin: get().nodeOrigin,
elevateNodesOnSelect: get().elevateNodesOnSelect,
});
@@ -80,13 +80,23 @@ const createRFStore = ({
set(nextState);
},
updateNodeDimensions: (updates) => {
const { onNodesChange, fitView, nodes, fitViewOnInit, fitViewDone, fitViewOnInitOptions, domNode, nodeOrigin } =
get();
const {
onNodesChange,
fitView,
nodes,
nodesLookup,
fitViewOnInit,
fitViewDone,
fitViewOnInitOptions,
domNode,
nodeOrigin,
} = get();
const changes: NodeDimensionChange[] = [];
const updatedNodes = updateNodeDimensionsSystem(
updates,
nodes,
nodesLookup,
domNode,
nodeOrigin,
(id: string, dimensions: Dimensions) => {
@@ -102,7 +112,7 @@ const createRFStore = ({
return;
}
const nextNodes = updateAbsolutePositions(updatedNodes, nodeOrigin);
const nextNodes = updateAbsolutePositions(updatedNodes, nodesLookup, nodeOrigin);
let nextFitViewDone = fitViewDone;
if (!fitViewDone && fitViewOnInit) {
@@ -138,12 +148,12 @@ const createRFStore = ({
},
triggerNodeChanges: (changes) => {
const { onNodesChange, nodes, hasDefaultNodes, nodeOrigin, elevateNodesOnSelect } = get();
const { onNodesChange, nodesLookup, nodes, hasDefaultNodes, nodeOrigin, elevateNodesOnSelect } = get();
if (changes?.length) {
if (hasDefaultNodes) {
const updatedNodes = applyNodeChanges(changes, nodes);
const nextNodes = updateNodes(updatedNodes, nodes, {
const nextNodes = updateNodes(updatedNodes, nodesLookup, {
nodeOrigin,
elevateNodesOnSelect,
});
+3 -1
View File
@@ -22,7 +22,8 @@ const getInitialState = ({
height?: number;
fitView?: boolean;
} = {}): ReactFlowStore => {
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 transform: Transform = [0, 0, 1];
@@ -43,6 +44,7 @@ const getInitialState = ({
height: 0,
transform,
nodes: nextNodes,
nodesLookup,
edges: edges,
onNodesChange: null,
onEdgesChange: null,
+2 -1
View File
@@ -46,6 +46,7 @@ export type ReactFlowStore = {
height: number;
transform: Transform;
nodes: Node[];
nodesLookup: Map<string, Node>;
edges: Edge[];
onNodesChange: OnNodesChange | null;
onEdgesChange: OnEdgesChange | null;
@@ -141,7 +142,7 @@ export type ReactFlowActions = {
getNodes: () => Node[];
setEdges: (edges: Edge[]) => void;
setDefaultNodesAndEdges: (nodes?: Node[], edges?: Edge[]) => void;
updateNodeDimensions: (updates: NodeDimensionUpdate[]) => void;
updateNodeDimensions: (updates: Map<string, NodeDimensionUpdate>) => void;
updateNodePositions: UpdateNodePositions;
resetSelectedElements: () => void;
unselectNodesAndEdges: (params?: UnselectNodesAndEdgesParams) => void;