From d6a410a0a3ef7ae462065b196d5aa83583f3d156 Mon Sep 17 00:00:00 2001 From: moklick Date: Wed, 18 Nov 2020 00:16:50 +0100 Subject: [PATCH] refactor(elementUpdater): simplify --- src/components/ElementUpdater/index.tsx | 137 +----------------------- src/store/index.ts | 52 ++++++++- 2 files changed, 53 insertions(+), 136 deletions(-) diff --git a/src/components/ElementUpdater/index.tsx b/src/components/ElementUpdater/index.tsx index a84c5c01..5bbe70a6 100644 --- a/src/components/ElementUpdater/index.tsx +++ b/src/components/ElementUpdater/index.tsx @@ -1,147 +1,18 @@ import { useEffect } from 'react'; -import isEqual from 'fast-deep-equal'; -import { useStoreState, useStoreActions } from '../../store/hooks'; -import { parseElement, isNode, isEdge } from '../../utils/graph'; -import { Elements, Node, Edge, FlowElement } from '../../types'; +import { useStoreActions } from '../../store/hooks'; +import { Elements } from '../../types'; interface ElementUpdaterProps { elements: Elements; } const ElementUpdater = ({ elements }: ElementUpdaterProps) => { - const stateElements = useStoreState((state) => state.elements); const setElements = useStoreActions((actions) => actions.setElements); useEffect(() => { - const nextElements: Elements = elements.map((propElement) => { - const existingElement = stateElements.find((el) => el.id === propElement.id?.toString()); - - if (existingElement) { - const data = !isEqual(existingElement.data, propElement.data) - ? { ...existingElement.data, ...propElement.data } - : existingElement.data; - - const style = !isEqual(existingElement.style, propElement.style) - ? { ...existingElement.style, ...propElement.style } - : existingElement.style; - - const elementProps = { - ...existingElement, - }; - - if (typeof data !== 'undefined') { - elementProps.data = data; - } - - if (typeof style !== 'undefined') { - elementProps.style = style; - } - - if (typeof propElement.className !== 'undefined') { - elementProps.className = propElement.className; - } - - if (typeof propElement.isHidden !== 'undefined') { - elementProps.isHidden = propElement.isHidden; - } - - if (typeof propElement.type !== 'undefined') { - elementProps.type = propElement.type; - - // we reset the elements dimensions here in order to force a re-calculation of the bounds. - // When the type of a node changes it is possible that the number or positions of handles changes too. - if (isNode(existingElement) && propElement.type !== existingElement.type) { - existingElement.__rf.width = null; - existingElement.__rf.height = null; - } - } - - if (isNode(existingElement)) { - const propNode = propElement as Node; - const nodeProps = elementProps as Node; - - const positionChanged = - existingElement.position.x !== propNode.position.x || existingElement.position.y !== propNode.position.y; - - if (positionChanged) { - nodeProps.__rf = { - ...existingElement.__rf, - position: propNode.position, - }; - nodeProps.position = propNode.position; - } - - if (typeof propNode.draggable !== 'undefined') { - nodeProps.draggable = propNode.draggable; - } - - if (typeof propNode.selectable !== 'undefined') { - nodeProps.selectable = propNode.selectable; - } - - if (typeof propNode.connectable !== 'undefined') { - nodeProps.connectable = propNode.connectable; - } - - return nodeProps; - } else if (isEdge(existingElement)) { - const propEdge = propElement as Edge; - const edgeProps = elementProps as Edge; - - const labelStyle = !isEqual(existingElement.labelStyle, propEdge.labelStyle) - ? { ...existingElement.labelStyle, ...propEdge.labelStyle } - : existingElement.labelStyle; - - const labelBgStyle = !isEqual(existingElement.labelBgStyle, propEdge.labelBgStyle) - ? { ...existingElement.labelBgStyle, ...propEdge.labelBgStyle } - : existingElement.labelBgStyle; - - if (typeof propEdge.label !== 'undefined') { - edgeProps.label = propEdge.label; - } - - if (typeof labelStyle !== 'undefined') { - edgeProps.labelStyle = labelStyle; - } - - if (typeof propEdge.labelShowBg !== 'undefined') { - edgeProps.labelShowBg = propEdge.labelShowBg; - } - - if (typeof propEdge.labelBgPadding !== 'undefined') { - edgeProps.labelBgPadding = propEdge.labelBgPadding; - } - - if (typeof propEdge.labelBgBorderRadius !== 'undefined') { - edgeProps.labelBgBorderRadius = propEdge.labelBgBorderRadius; - } - - if (typeof labelBgStyle !== 'undefined') { - edgeProps.labelBgStyle = labelBgStyle; - } - - if (typeof propEdge.animated !== 'undefined') { - edgeProps.animated = propEdge.animated; - } - - if (typeof propEdge.arrowHeadType !== 'undefined') { - edgeProps.arrowHeadType = propEdge.arrowHeadType; - } - - return edgeProps; - } - } - - return parseElement(propElement) as FlowElement; - }); - - const elementsChanged: boolean = !isEqual(stateElements, nextElements); - - if (elementsChanged) { - setElements(nextElements); - } - }, [elements, stateElements]); + setElements(elements); + }, [elements]); return null; }; diff --git a/src/store/index.ts b/src/store/index.ts index 5c33c697..9cc7f7f8 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -3,7 +3,7 @@ import isEqual from 'fast-deep-equal'; import { Selection as D3Selection, ZoomBehavior } from 'd3'; import { getDimensions } from '../utils'; -import { getNodesInside, getConnectedEdges, getRectOfNodes, isNode, isEdge } from '../utils/graph'; +import { getNodesInside, getConnectedEdges, getRectOfNodes, isNode, isEdge, parseElement } from '../utils/graph'; import { getHandleBounds } from '../components/Nodes/utils'; import { @@ -196,8 +196,54 @@ export const storeModel: StoreModel = { state.onConnectEnd = onConnectEnd; }), - setElements: action((state, elements) => { - state.elements = elements; + setElements: action((state, propElements) => { + // remove deleted elements + state.elements.forEach((se, i) => { + const removeElement = !propElements.some((pe) => pe.id === se.id); + + if (removeElement) { + state.elements.splice(i, 1); + } + }); + + propElements.forEach((el) => { + const storeElementIndex = state.elements.findIndex((se) => se.id === el.id); + + // update existing element + if (storeElementIndex !== -1) { + const storeElement = state.elements[storeElementIndex]; + + state.elements[storeElementIndex] = { + ...storeElement, + ...el, + }; + + if (isNode(state.elements[storeElementIndex])) { + const propNode = el as Node; + const storeNode = state.elements[storeElementIndex] as Node; + + const poitionChanged = + storeNode.position.x !== propNode.position.x || storeNode.position.y !== propNode.position.y; + + if (poitionChanged) { + (state.elements[storeElementIndex] as Node).__rf = { + ...storeNode.__rf, + position: propNode.position, + }; + } + + // we reset the elements dimensions here in order to force a re-calculation of the bounds. + // When the type of a node changes it is possible that the number or positions of handles changes too. + if (propNode.type !== storeNode.type) { + (state.elements[storeElementIndex] as Node).__rf.width = null; + (state.elements[storeElementIndex] as Node).__rf.height = null; + } + } + } else { + // add new element + state.elements.push(parseElement(el)); + } + }); }), updateNodeDimensions: action((state, { id, nodeElement }) => {