From 56cfc8d731b8f4cb06a8c6332e4cd281eaf5021b Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 25 May 2020 17:12:11 +0200 Subject: [PATCH] refactor(easy-peasy): return single values from useStoreState --- .../Background/index.tsx | 8 ++- src/additional-components/Controls/index.tsx | 2 +- src/additional-components/MiniMap/index.tsx | 26 ++++------ src/components/NodesSelection/index.tsx | 50 +++++++++---------- src/container/EdgeRenderer/index.tsx | 33 ++++-------- src/container/GraphView/index.tsx | 23 ++++----- src/container/NodeRenderer/index.tsx | 19 +++---- src/hooks/useD3Zoom.ts | 22 +++----- src/hooks/useElementUpdater.ts | 17 +++---- src/hooks/useGlobalKeyHandler.ts | 23 ++++----- 10 files changed, 93 insertions(+), 130 deletions(-) diff --git a/src/additional-components/Background/index.tsx b/src/additional-components/Background/index.tsx index 93262819..782dd1b4 100644 --- a/src/additional-components/Background/index.tsx +++ b/src/additional-components/Background/index.tsx @@ -25,11 +25,9 @@ const defaultColors = { const Background = memo( ({ variant = BackgroundVariant.Dots, gap = 24, size = 0.5, color, style = {}, className = '' }: BackgroundProps) => { - const { - width, - height, - transform: [x, y, scale], - } = useStoreState((s) => s); + const width = useStoreState((s) => s.width); + const height = useStoreState((s) => s.height); + const [x, y, scale] = useStoreState((s) => s.transform); const bgClasses = classnames('react-flow__background', className); const bgColor = color ? color : defaultColors[variant]; diff --git a/src/additional-components/Controls/index.tsx b/src/additional-components/Controls/index.tsx index a26da2c0..44bf2f7f 100644 --- a/src/additional-components/Controls/index.tsx +++ b/src/additional-components/Controls/index.tsx @@ -25,7 +25,7 @@ interface ControlProps extends React.HTMLAttributes { const Controls = ({ style, showZoom = true, showFitView = true, showInteractive = true, className }: ControlProps) => { const setInteractive = useStoreActions((actions) => actions.setInteractive); - const { isInteractive } = useStoreState(({ isInteractive }) => ({ isInteractive })); + const isInteractive = useStoreState((s) => s.isInteractive); const mapClasses: string = classnames('react-flow__controls', className); return ( diff --git a/src/additional-components/MiniMap/index.tsx b/src/additional-components/MiniMap/index.tsx index 45b1486f..bb58ab20 100644 --- a/src/additional-components/MiniMap/index.tsx +++ b/src/additional-components/MiniMap/index.tsx @@ -30,27 +30,23 @@ const MiniMap = ({ nodeBorderRadius = 5, maskColor = 'rgba(10, 10, 10, .25)', }: MiniMapProps) => { - const state = useStoreState(({ width, height, nodes, transform: [tX, tY, tScale] }) => ({ - width, - height, - nodes, - tX, - tY, - tScale, - })); + const containerWidth = useStoreState((s) => s.width); + const containerHeight = useStoreState((s) => s.height); + const [tX, tY, tScale] = useStoreState((s) => s.transform); + const nodes = useStoreState((s) => s.nodes); const mapClasses = classnames('react-flow__minimap', className); const elementWidth = (style.width || baseStyle.width)! as number; const elementHeight = (style.height || baseStyle.height)! as number; const nodeColorFunc = (nodeColor instanceof Function ? nodeColor : () => nodeColor) as StringFunc; - const hasNodes = state.nodes && state.nodes.length; + const hasNodes = nodes && nodes.length; - const bb = getRectOfNodes(state.nodes); + const bb = getRectOfNodes(nodes); const viewBB: Rect = { - x: -state.tX / state.tScale, - y: -state.tY / state.tScale, - width: state.width / state.tScale, - height: state.height / state.tScale, + x: -tX / tScale, + y: -tY / tScale, + width: containerWidth / tScale, + height: containerHeight / tScale, }; const boundingRect = hasNodes ? getBoundsofRects(bb, viewBB) : viewBB; @@ -79,7 +75,7 @@ const MiniMap = ({ }} className={mapClasses} > - {state.nodes.map((node) => ( + {nodes.map((node) => ( ))} { const [offset, setOffset] = useState({ x: 0, y: 0 }); const [startPositions, setStartPositions] = useState({}); - const state = useStoreState((s) => ({ - transform: s.transform, - selectedNodesBbox: s.selectedNodesBbox, - selectedElements: s.selectedElements, - snapToGrid: s.snapToGrid, - snapGrid: s.snapGrid, - nodes: s.nodes, - })); + const [tX, tY, tScale] = useStoreState((s) => s.transform); + const selectedNodesBbox = useStoreState((s) => s.selectedNodesBbox); + const selectedElements = useStoreState((s) => s.selectedElements); + const snapToGrid = useStoreState((s) => s.snapToGrid); + const snapGrid = useStoreState((s) => s.snapGrid); + const nodes = useStoreState((s) => s.nodes); + const updateNodePos = useStoreActions((a) => a.updateNodePos); - const [tx, ty, tScale] = state.transform; - const position = state.selectedNodesBbox; - const grid = (state.snapToGrid ? state.snapGrid : [1, 1])! as [number, number]; + const position = selectedNodesBbox; + const grid = (snapToGrid ? snapGrid : [1, 1])! as [number, number]; const onStart = (evt: MouseEvent) => { const scaledClient: XYPosition = { x: evt.clientX / tScale, y: evt.clientY / tScale, }; - const offsetX: number = scaledClient.x - position.x - tx; - const offsetY: number = scaledClient.y - position.y - ty; - const selectedNodes = state.selectedElements - ? (state.selectedElements.filter(isNode) as Node[]).map( - (selectedNode) => state.nodes.find((node) => node.id === selectedNode.id)! as Node - ) + const offsetX: number = scaledClient.x - position.x - tX; + const offsetY: number = scaledClient.y - position.y - tY; + const selectedNodes = selectedElements + ? selectedElements + .filter(isNode) + .map((selectedNode) => nodes.find((node) => node.id === selectedNode.id)! as Node) : []; const nextStartPositions = getStartPositions(selectedNodes); @@ -70,11 +68,11 @@ export default memo(() => { y: evt.clientY / tScale, }; - if (state.selectedElements) { - (state.selectedElements.filter(isNode) as Node[]).forEach((node) => { + if (selectedElements) { + selectedElements.filter(isNode).forEach((node) => { const pos: XYPosition = { - x: startPositions[node.id].x + scaledClient.x - position.x - offset.x - tx, - y: startPositions[node.id].y + scaledClient.y - position.y - offset.y - ty, + x: startPositions[node.id].x + scaledClient.x - position.x - offset.x - tX, + y: startPositions[node.id].y + scaledClient.y - position.y - offset.y - tY, }; updateNodePos({ id: node.id, pos }); @@ -86,7 +84,7 @@ export default memo(() => {
{
diff --git a/src/container/EdgeRenderer/index.tsx b/src/container/EdgeRenderer/index.tsx index 351b3b34..a25b0167 100644 --- a/src/container/EdgeRenderer/index.tsx +++ b/src/container/EdgeRenderer/index.tsx @@ -187,23 +187,13 @@ function renderEdge( } const EdgeRenderer = memo((props: EdgeRendererProps) => { - const { - transform, - edges, - nodes, - connectionSourceId, - connectionPosition: { x, y }, - selectedElements, - isInteractive, - } = useStoreState((s) => ({ - transform: s.transform, - edges: s.edges, - nodes: s.nodes, - connectionSourceId: s.connectionSourceId, - connectionPosition: s.connectionPosition, - selectedElements: s.selectedElements, - isInteractive: s.isInteractive, - })); + const [tX, tY, tScale] = useStoreState((s) => s.transform); + const edges = useStoreState((s) => s.edges); + const nodes = useStoreState((s) => s.nodes); + const connectionSourceId = useStoreState((s) => s.connectionSourceId); + const connectionPosition = useStoreState((s) => s.connectionPosition); + const selectedElements = useStoreState((s) => s.selectedElements); + const isInteractive = useStoreState((s) => s.isInteractive); const { width, height, connectionLineStyle, connectionLineType } = props; @@ -211,8 +201,7 @@ const EdgeRenderer = memo((props: EdgeRendererProps) => { return null; } - const [tx, ty, tScale] = transform; - const transformStyle = `translate(${tx},${ty}) scale(${tScale})`; + const transformStyle = `translate(${tX},${tY}) scale(${tScale})`; return ( @@ -222,9 +211,9 @@ const EdgeRenderer = memo((props: EdgeRendererProps) => { { const zoomPane = useRef(null); const rendererNode = useRef(null); - const state = useStoreState((s) => ({ - width: s.width, - height: s.height, - nodes: s.nodes, - edges: s.edges, - d3Initialised: s.d3Initialised, - nodesSelectionActive: s.nodesSelectionActive, - })); + const width = useStoreState((s) => s.width); + const height = useStoreState((s) => s.height); + const d3Initialised = useStoreState((s) => s.d3Initialised); + const nodesSelectionActive = useStoreState((s) => s.nodesSelectionActive); + const updateSize = useStoreActions((actions) => actions.updateSize); const setNodesSelection = useStoreActions((actions) => actions.setNodesSelection); const setOnConnect = useStoreActions((a) => a.setOnConnect); @@ -106,7 +103,7 @@ const GraphView = memo( useD3Zoom({ zoomPane, onMove, selectionKeyPressed }); useEffect(() => { - if (state.d3Initialised && onLoad) { + if (d3Initialised && onLoad) { onLoad({ fitView, zoomIn, @@ -114,7 +111,7 @@ const GraphView = memo( project, }); } - }, [state.d3Initialised, onLoad]); + }, [d3Initialised, onLoad]); useEffect(() => { setSnapGrid({ snapToGrid, snapGrid }); @@ -137,15 +134,15 @@ const GraphView = memo( onlyRenderVisibleNodes={onlyRenderVisibleNodes} /> {selectionKeyPressed && } - {state.nodesSelectionActive && } + {nodesSelectionActive && }
); diff --git a/src/container/NodeRenderer/index.tsx b/src/container/NodeRenderer/index.tsx index 05f1e32c..8f8ffe65 100644 --- a/src/container/NodeRenderer/index.tsx +++ b/src/container/NodeRenderer/index.tsx @@ -49,18 +49,15 @@ function renderNode( } const NodeRenderer = memo(({ onlyRenderVisibleNodes = true, ...props }: NodeRendererProps) => { - const { nodes, transform, selectedElements, width, height, isInteractive } = useStoreState((s) => ({ - nodes: s.nodes, - transform: s.transform, - selectedElements: s.selectedElements, - width: s.width, - height: s.height, - isInteractive: s.isInteractive, - })); - - const [tx, ty, tScale] = transform; + const nodes = useStoreState((s) => s.nodes); + const transform = useStoreState((s) => s.transform); + const selectedElements = useStoreState((s) => s.selectedElements); + const width = useStoreState((s) => s.width); + const height = useStoreState((s) => s.height); + const isInteractive = useStoreState((s) => s.isInteractive); + const [tX, tY, tScale] = transform; const transformStyle = { - transform: `translate(${tx}px,${ty}px) scale(${tScale})`, + transform: `translate(${tX}px,${tY}px) scale(${tScale})`, }; const renderNodes = onlyRenderVisibleNodes diff --git a/src/hooks/useD3Zoom.ts b/src/hooks/useD3Zoom.ts index fc0527e3..0cd64333 100644 --- a/src/hooks/useD3Zoom.ts +++ b/src/hooks/useD3Zoom.ts @@ -1,5 +1,5 @@ import { useEffect, MutableRefObject } from 'react'; -import * as d3Zoom from 'd3-zoom'; +import { zoom, zoomIdentity } from 'd3-zoom'; import { select, event } from 'd3-selection'; import { useStoreState, useStoreActions } from '../store/hooks'; @@ -10,17 +10,14 @@ interface UseD3ZoomParams { onMove?: () => void; } -const d3ZoomInstance = d3Zoom - .zoom() +const d3ZoomInstance = zoom() .scaleExtent([0.5, 2]) .filter(() => !event.button); export default ({ zoomPane, onMove, selectionKeyPressed }: UseD3ZoomParams): void => { - const state = useStoreState((s) => ({ - transform: s.transform, - d3Selection: s.d3Selection, - d3Zoom: s.d3Zoom, - })); + const transform = useStoreState((s) => s.transform); + const d3Selection = useStoreState((s) => s.d3Selection); + const d3Zoom = useStoreState((s) => s.d3Zoom); const initD3 = useStoreActions((actions) => actions.initD3); const updateTransform = useStoreActions((actions) => actions.updateTransform); @@ -48,13 +45,10 @@ export default ({ zoomPane, onMove, selectionKeyPressed }: UseD3ZoomParams): voi } }); - if (state.d3Selection && state.d3Zoom) { + if (d3Selection && d3Zoom) { // we need to restore the graph transform otherwise d3 zoom transform and graph transform are not synced - const graphTransform = d3Zoom.zoomIdentity - .translate(state.transform[0], state.transform[1]) - .scale(state.transform[2]); - - state.d3Selection.call(state.d3Zoom.transform, graphTransform); + const graphTransform = zoomIdentity.translate(transform[0], transform[1]).scale(transform[2]); + d3Selection.call(d3Zoom.transform, graphTransform); } } diff --git a/src/hooks/useElementUpdater.ts b/src/hooks/useElementUpdater.ts index 17bdcdfa..79b09444 100644 --- a/src/hooks/useElementUpdater.ts +++ b/src/hooks/useElementUpdater.ts @@ -6,13 +6,8 @@ import { parseElement, isNode, isEdge } from '../utils/graph'; import { Elements, Node, Edge } from '../types'; const useElementUpdater = (elements: Elements): void => { - const state = useStoreState((s) => ({ - nodes: s.nodes, - edges: s.edges, - transform: s.transform, - snapToGrid: s.snapToGrid, - snapGrid: s.snapGrid, - })); + const stateNodes = useStoreState((s) => s.nodes); + const stateEdges = useStoreState((s) => s.edges); const setNodes = useStoreActions((a) => a.setNodes); const setEdges = useStoreActions((a) => a.setEdges); @@ -22,7 +17,7 @@ const useElementUpdater = (elements: Elements): void => { const edges: Edge[] = elements.filter(isEdge).map((e) => parseElement(e) as Edge); const nextNodes: Node[] = nodes.map((propNode) => { - const existingNode = state.nodes.find((n) => n.id === propNode.id); + const existingNode = stateNodes.find((n) => n.id === propNode.id); if (existingNode) { const data = !isEqual(existingNode.data, propNode.data) @@ -59,8 +54,8 @@ const useElementUpdater = (elements: Elements): void => { return parseElement(propNode) as Node; }); - const nodesChanged: boolean = !isEqual(state.nodes, nextNodes); - const edgesChanged: boolean = !isEqual(state.edges, edges); + const nodesChanged: boolean = !isEqual(stateNodes, nextNodes); + const edgesChanged: boolean = !isEqual(stateEdges, edges); if (nodesChanged) { setNodes(nextNodes); @@ -69,7 +64,7 @@ const useElementUpdater = (elements: Elements): void => { if (edgesChanged) { setEdges(edges); } - }, [elements, state.nodes, state.edges]); + }, [elements, stateNodes, stateEdges]); }; export default useElementUpdater; diff --git a/src/hooks/useGlobalKeyHandler.ts b/src/hooks/useGlobalKeyHandler.ts index c30c1f2f..cce41486 100644 --- a/src/hooks/useGlobalKeyHandler.ts +++ b/src/hooks/useGlobalKeyHandler.ts @@ -2,8 +2,8 @@ import { useEffect } from 'react'; import { useStoreState, useStoreActions } from '../store/hooks'; import useKeyPress from './useKeyPress'; -import { isEdge, getConnectedEdges } from '../utils/graph'; -import { Elements, Node } from '../types'; +import { isNode, getConnectedEdges } from '../utils/graph'; +import { Elements } from '../types'; interface HookParams { deleteKeyCode: number; @@ -11,22 +11,21 @@ interface HookParams { } export default ({ deleteKeyCode, onElementsRemove }: HookParams): void => { - const state = useStoreState((s) => ({ - selectedElements: s.selectedElements, - edges: s.edges, - })); + const selectedElements = useStoreState((s) => s.selectedElements); + const edges = useStoreState((s) => s.edges); + const setNodesSelection = useStoreActions((a) => a.setNodesSelection); const deleteKeyPressed = useKeyPress(deleteKeyCode); useEffect(() => { - if (onElementsRemove && deleteKeyPressed && state.selectedElements) { - let elementsToRemove = state.selectedElements; + if (onElementsRemove && deleteKeyPressed && selectedElements) { + let elementsToRemove = selectedElements; // we also want to remove the edges if only one node is selected - if (state.selectedElements.length === 1 && !isEdge(state.selectedElements[0])) { - const node = (state.selectedElements[0] as unknown) as Node; - const connectedEdges = getConnectedEdges([node], state.edges); - elementsToRemove = [...state.selectedElements, ...connectedEdges]; + if (selectedElements.length === 1 && isNode(selectedElements[0])) { + const node = selectedElements[0]; + const connectedEdges = getConnectedEdges([node], edges); + elementsToRemove = [...selectedElements, ...connectedEdges]; } onElementsRemove(elementsToRemove);