refactor(GraphView): reduce amounts of re-renderings
This commit is contained in:
@@ -1,16 +1,20 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import isEqual from 'fast-deep-equal';
|
import isEqual from 'fast-deep-equal';
|
||||||
|
|
||||||
import { useStoreState, useStoreActions } from '../store/hooks';
|
import { useStoreState, useStoreActions } from '../../store/hooks';
|
||||||
import { parseElement, isNode, isEdge } from '../utils/graph';
|
import { parseElement, isNode, isEdge } from '../../utils/graph';
|
||||||
import { Elements, Node, Edge, FlowElement } from '../types';
|
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 stateElements = useStoreState((state) => state.elements);
|
||||||
const setElements = useStoreActions((actions) => actions.setElements);
|
const setElements = useStoreActions((actions) => actions.setElements);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const nextElements: Elements = propElements.map((propElement) => {
|
const nextElements: Elements = elements.map((propElement) => {
|
||||||
const existingElement = stateElements.find((el) => el.id === propElement.id?.toString());
|
const existingElement = stateElements.find((el) => el.id === propElement.id?.toString());
|
||||||
|
|
||||||
if (existingElement) {
|
if (existingElement) {
|
||||||
@@ -137,7 +141,9 @@ const useElementUpdater = (propElements: Elements): void => {
|
|||||||
if (elementsChanged) {
|
if (elementsChanged) {
|
||||||
setElements(nextElements);
|
setElements(nextElements);
|
||||||
}
|
}
|
||||||
}, [propElements, stateElements]);
|
}, [elements, stateElements]);
|
||||||
|
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default useElementUpdater;
|
export default ElementUpdater;
|
||||||
@@ -4,7 +4,6 @@ import { useStoreActions, useStore } from '../../store/hooks';
|
|||||||
import FlowRenderer from '../FlowRenderer';
|
import FlowRenderer from '../FlowRenderer';
|
||||||
import NodeRenderer from '../NodeRenderer';
|
import NodeRenderer from '../NodeRenderer';
|
||||||
import EdgeRenderer from '../EdgeRenderer';
|
import EdgeRenderer from '../EdgeRenderer';
|
||||||
import useElementUpdater from '../../hooks/useElementUpdater';
|
|
||||||
import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph';
|
import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph';
|
||||||
import useZoomPanHelper from '../../hooks/useZoomPanHelper';
|
import useZoomPanHelper from '../../hooks/useZoomPanHelper';
|
||||||
|
|
||||||
@@ -12,7 +11,7 @@ import { ReactFlowProps } from '../ReactFlow';
|
|||||||
|
|
||||||
import { NodeTypesType, EdgeTypesType, ConnectionLineType } from '../../types';
|
import { NodeTypesType, EdgeTypesType, ConnectionLineType } from '../../types';
|
||||||
|
|
||||||
export interface GraphViewProps extends Omit<ReactFlowProps, 'onSelectionChange'> {
|
export interface GraphViewProps extends Omit<ReactFlowProps, 'onSelectionChange' | 'elements'> {
|
||||||
nodeTypes: NodeTypesType;
|
nodeTypes: NodeTypesType;
|
||||||
edgeTypes: EdgeTypesType;
|
edgeTypes: EdgeTypesType;
|
||||||
selectionKeyCode: number;
|
selectionKeyCode: number;
|
||||||
@@ -53,7 +52,6 @@ const GraphView = ({
|
|||||||
multiSelectionKeyCode,
|
multiSelectionKeyCode,
|
||||||
onElementsRemove,
|
onElementsRemove,
|
||||||
deleteKeyCode,
|
deleteKeyCode,
|
||||||
elements,
|
|
||||||
onConnect,
|
onConnect,
|
||||||
onConnectStart,
|
onConnectStart,
|
||||||
onConnectStop,
|
onConnectStop,
|
||||||
@@ -97,8 +95,6 @@ const GraphView = ({
|
|||||||
const currentStore = useStore();
|
const currentStore = useStore();
|
||||||
const { zoomIn, zoomOut, zoomTo, transform, fitView } = useZoomPanHelper();
|
const { zoomIn, zoomOut, zoomTo, transform, fitView } = useZoomPanHelper();
|
||||||
|
|
||||||
useElementUpdater(elements);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isInitialised.current && zoomIn && zoomOut && zoomTo && transform && fitView) {
|
if (!isInitialised.current && zoomIn && zoomOut && zoomTo && transform && fitView) {
|
||||||
if (onLoad) {
|
if (onLoad) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ if (nodeEnv !== 'production') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
import GraphView from '../GraphView';
|
import GraphView from '../GraphView';
|
||||||
|
import ElementUpdater from '../../components/ElementUpdater';
|
||||||
import DefaultNode from '../../components/Nodes/DefaultNode';
|
import DefaultNode from '../../components/Nodes/DefaultNode';
|
||||||
import InputNode from '../../components/Nodes/InputNode';
|
import InputNode from '../../components/Nodes/InputNode';
|
||||||
import OutputNode from '../../components/Nodes/OutputNode';
|
import OutputNode from '../../components/Nodes/OutputNode';
|
||||||
@@ -189,7 +190,6 @@ const ReactFlow = ({
|
|||||||
onElementsRemove={onElementsRemove}
|
onElementsRemove={onElementsRemove}
|
||||||
deleteKeyCode={deleteKeyCode}
|
deleteKeyCode={deleteKeyCode}
|
||||||
multiSelectionKeyCode={multiSelectionKeyCode}
|
multiSelectionKeyCode={multiSelectionKeyCode}
|
||||||
elements={elements}
|
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onConnectStart={onConnectStart}
|
onConnectStart={onConnectStart}
|
||||||
onConnectStop={onConnectStop}
|
onConnectStop={onConnectStop}
|
||||||
@@ -221,6 +221,7 @@ const ReactFlow = ({
|
|||||||
onSelectionDragStop={onSelectionDragStop}
|
onSelectionDragStop={onSelectionDragStop}
|
||||||
onSelectionContextMenu={onSelectionContextMenu}
|
onSelectionContextMenu={onSelectionContextMenu}
|
||||||
/>
|
/>
|
||||||
|
<ElementUpdater elements={elements} />
|
||||||
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
||||||
{children}
|
{children}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
|
|||||||
@@ -55,13 +55,13 @@ const ZoomPane = ({
|
|||||||
const zoomPane = useRef<HTMLDivElement>(null);
|
const zoomPane = useRef<HTMLDivElement>(null);
|
||||||
const prevTransform = useRef<FlowTransform>({ x: 0, y: 0, zoom: 0 });
|
const prevTransform = useRef<FlowTransform>({ x: 0, y: 0, zoom: 0 });
|
||||||
|
|
||||||
|
const store = useStore();
|
||||||
const d3Zoom = useStoreState((s) => s.d3Zoom);
|
const d3Zoom = useStoreState((s) => s.d3Zoom);
|
||||||
const d3Selection = useStoreState((s) => s.d3Selection);
|
const d3Selection = useStoreState((s) => s.d3Selection);
|
||||||
const d3ZoomHandler = useStoreState((s) => s.d3ZoomHandler);
|
const d3ZoomHandler = useStoreState((s) => s.d3ZoomHandler);
|
||||||
|
|
||||||
const initD3Zoom = useStoreActions((actions) => actions.initD3Zoom);
|
const initD3Zoom = useStoreActions((actions) => actions.initD3Zoom);
|
||||||
const updateTransform = useStoreActions((actions) => actions.updateTransform);
|
const updateTransform = useStoreActions((actions) => actions.updateTransform);
|
||||||
const store = useStore();
|
|
||||||
|
|
||||||
useResizeHandler(zoomPane);
|
useResizeHandler(zoomPane);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
import { useStoreState, useStoreActions } from '../store/hooks';
|
import { useStore, useStoreActions } from '../store/hooks';
|
||||||
import useKeyPress from './useKeyPress';
|
import useKeyPress from './useKeyPress';
|
||||||
import { isNode, getConnectedEdges } from '../utils/graph';
|
import { isNode, getConnectedEdges } from '../utils/graph';
|
||||||
import { Elements } from '../types';
|
import { Elements } from '../types';
|
||||||
@@ -12,8 +12,7 @@ interface HookParams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: HookParams): void => {
|
export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: HookParams): void => {
|
||||||
const selectedElements = useStoreState((state) => state.selectedElements);
|
const store = useStore();
|
||||||
const edges = useStoreState((state) => state.edges);
|
|
||||||
|
|
||||||
const unsetNodesSelection = useStoreActions((actions) => actions.unsetNodesSelection);
|
const unsetNodesSelection = useStoreActions((actions) => actions.unsetNodesSelection);
|
||||||
const setMultiSelectionActive = useStoreActions((actions) => actions.setMultiSelectionActive);
|
const setMultiSelectionActive = useStoreActions((actions) => actions.setMultiSelectionActive);
|
||||||
@@ -23,6 +22,7 @@ export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: Hook
|
|||||||
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
|
const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const { edges, selectedElements } = store.getState();
|
||||||
if (onElementsRemove && deleteKeyPressed && selectedElements) {
|
if (onElementsRemove && deleteKeyPressed && selectedElements) {
|
||||||
let elementsToRemove = selectedElements;
|
let elementsToRemove = selectedElements;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user