From 0fbefe5a58f193cdba037aad07a0f5b80c452884 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 9 Nov 2020 22:24:12 +0100 Subject: [PATCH] refactor(GraphView): reduce amounts of re-renderings --- .../ElementUpdater/index.tsx} | 20 ++++++++++++------- src/container/GraphView/index.tsx | 6 +----- src/container/ReactFlow/index.tsx | 3 ++- src/container/ZoomPane/index.tsx | 2 +- src/hooks/useGlobalKeyHandler.ts | 6 +++--- 5 files changed, 20 insertions(+), 17 deletions(-) rename src/{hooks/useElementUpdater.ts => components/ElementUpdater/index.tsx} (90%) diff --git a/src/hooks/useElementUpdater.ts b/src/components/ElementUpdater/index.tsx similarity index 90% rename from src/hooks/useElementUpdater.ts rename to src/components/ElementUpdater/index.tsx index 0f2bac7c..a84c5c01 100644 --- a/src/hooks/useElementUpdater.ts +++ b/src/components/ElementUpdater/index.tsx @@ -1,16 +1,20 @@ 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 { useStoreState, useStoreActions } from '../../store/hooks'; +import { parseElement, isNode, isEdge } from '../../utils/graph'; +import { Elements, Node, Edge, FlowElement } from '../../types'; -const useElementUpdater = (propElements: Elements): void => { +interface ElementUpdaterProps { + elements: Elements; +} + +const ElementUpdater = ({ elements }: ElementUpdaterProps) => { const stateElements = useStoreState((state) => state.elements); const setElements = useStoreActions((actions) => actions.setElements); useEffect(() => { - const nextElements: Elements = propElements.map((propElement) => { + const nextElements: Elements = elements.map((propElement) => { const existingElement = stateElements.find((el) => el.id === propElement.id?.toString()); if (existingElement) { @@ -137,7 +141,9 @@ const useElementUpdater = (propElements: Elements): void => { if (elementsChanged) { setElements(nextElements); } - }, [propElements, stateElements]); + }, [elements, stateElements]); + + return null; }; -export default useElementUpdater; +export default ElementUpdater; diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index c831b367..2c870ab3 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -4,7 +4,6 @@ import { useStoreActions, useStore } from '../../store/hooks'; import FlowRenderer from '../FlowRenderer'; import NodeRenderer from '../NodeRenderer'; import EdgeRenderer from '../EdgeRenderer'; -import useElementUpdater from '../../hooks/useElementUpdater'; import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph'; import useZoomPanHelper from '../../hooks/useZoomPanHelper'; @@ -12,7 +11,7 @@ import { ReactFlowProps } from '../ReactFlow'; import { NodeTypesType, EdgeTypesType, ConnectionLineType } from '../../types'; -export interface GraphViewProps extends Omit { +export interface GraphViewProps extends Omit { nodeTypes: NodeTypesType; edgeTypes: EdgeTypesType; selectionKeyCode: number; @@ -53,7 +52,6 @@ const GraphView = ({ multiSelectionKeyCode, onElementsRemove, deleteKeyCode, - elements, onConnect, onConnectStart, onConnectStop, @@ -97,8 +95,6 @@ const GraphView = ({ const currentStore = useStore(); const { zoomIn, zoomOut, zoomTo, transform, fitView } = useZoomPanHelper(); - useElementUpdater(elements); - useEffect(() => { if (!isInitialised.current && zoomIn && zoomOut && zoomTo && transform && fitView) { if (onLoad) { diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index 533d2100..8a4860b5 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -9,6 +9,7 @@ if (nodeEnv !== 'production') { } import GraphView from '../GraphView'; +import ElementUpdater from '../../components/ElementUpdater'; import DefaultNode from '../../components/Nodes/DefaultNode'; import InputNode from '../../components/Nodes/InputNode'; import OutputNode from '../../components/Nodes/OutputNode'; @@ -189,7 +190,6 @@ const ReactFlow = ({ onElementsRemove={onElementsRemove} deleteKeyCode={deleteKeyCode} multiSelectionKeyCode={multiSelectionKeyCode} - elements={elements} onConnect={onConnect} onConnectStart={onConnectStart} onConnectStop={onConnectStop} @@ -221,6 +221,7 @@ const ReactFlow = ({ onSelectionDragStop={onSelectionDragStop} onSelectionContextMenu={onSelectionContextMenu} /> + {onSelectionChange && } {children} diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 3d2d94e3..e67c253d 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -55,13 +55,13 @@ const ZoomPane = ({ const zoomPane = useRef(null); const prevTransform = useRef({ x: 0, y: 0, zoom: 0 }); + const store = useStore(); const d3Zoom = useStoreState((s) => s.d3Zoom); const d3Selection = useStoreState((s) => s.d3Selection); const d3ZoomHandler = useStoreState((s) => s.d3ZoomHandler); const initD3Zoom = useStoreActions((actions) => actions.initD3Zoom); const updateTransform = useStoreActions((actions) => actions.updateTransform); - const store = useStore(); useResizeHandler(zoomPane); diff --git a/src/hooks/useGlobalKeyHandler.ts b/src/hooks/useGlobalKeyHandler.ts index a6319b3d..1a719f4c 100644 --- a/src/hooks/useGlobalKeyHandler.ts +++ b/src/hooks/useGlobalKeyHandler.ts @@ -1,6 +1,6 @@ import { useEffect } from 'react'; -import { useStoreState, useStoreActions } from '../store/hooks'; +import { useStore, useStoreActions } from '../store/hooks'; import useKeyPress from './useKeyPress'; import { isNode, getConnectedEdges } from '../utils/graph'; import { Elements } from '../types'; @@ -12,8 +12,7 @@ interface HookParams { } export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: HookParams): void => { - const selectedElements = useStoreState((state) => state.selectedElements); - const edges = useStoreState((state) => state.edges); + const store = useStore(); const unsetNodesSelection = useStoreActions((actions) => actions.unsetNodesSelection); const setMultiSelectionActive = useStoreActions((actions) => actions.setMultiSelectionActive); @@ -23,6 +22,7 @@ export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: Hook const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode); useEffect(() => { + const { edges, selectedElements } = store.getState(); if (onElementsRemove && deleteKeyPressed && selectedElements) { let elementsToRemove = selectedElements;