From d1a5bc75ab711c5acca651a303601819faa6a169 Mon Sep 17 00:00:00 2001 From: Ivan Akulov Date: Fri, 24 Nov 2023 22:24:03 +0100 Subject: [PATCH] Optimize MiniMapNodes like NodeRenderer --- .../MiniMap/MiniMapNodes.tsx | 117 +++++++++++++----- 1 file changed, 83 insertions(+), 34 deletions(-) diff --git a/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx b/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx index 80ac09be..f4e40e00 100644 --- a/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx +++ b/packages/react/src/additional-components/MiniMap/MiniMapNodes.tsx @@ -1,21 +1,30 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { memo } from 'react'; +import { ComponentType, memo, MouseEvent } from 'react'; import { shallow } from 'zustand/shallow'; -import { getNodePositionWithOrigin } from '@xyflow/system'; +import { NodeOrigin, getNodePositionWithOrigin } from '@xyflow/system'; import { useStore } from '../../hooks/useStore'; import type { ReactFlowState } from '../../types'; import MiniMapNode from './MiniMapNode'; -import type { MiniMapNodes, GetMiniMapNodeAttribute } from './types'; +import type { MiniMapNodes as MiniMapNodesProps, GetMiniMapNodeAttribute, MiniMapNodeProps } from './types'; +import { createSelector } from 'reselect'; declare const window: any; const selector = (s: ReactFlowState) => s.nodeOrigin; -const selectorNodes = (s: ReactFlowState) => - s.nodes.filter( - (node) => !node.hidden && (node.computed?.width || node.width) && (node.computed?.height || node.height) - ); +const selectorNodeIds = createSelector( + [(s: ReactFlowState) => s.nodes], + (nodes) => + nodes + .filter((node) => !node.hidden && (node.computed?.width || node.width) && (node.computed?.height || node.height)) + .map((node) => node.id), + { + memoizeOptions: { + resultEqualityCheck: shallow, + }, + } +); const getAttrFunction = (func: any): GetMiniMapNodeAttribute => (func instanceof Function ? func : () => func); function MiniMapNodes({ @@ -28,8 +37,8 @@ function MiniMapNodes({ // a component properly. nodeComponent: NodeComponent = MiniMapNode, onClick, -}: MiniMapNodes) { - const nodes = useStore(selectorNodes, shallow); +}: MiniMapNodesProps) { + const nodes = useStore(selectorNodeIds); const nodeOrigin = useStore(selector); const nodeColorFunc = getAttrFunction(nodeColor); const nodeStrokeColorFunc = getAttrFunction(nodeStrokeColor); @@ -39,33 +48,73 @@ function MiniMapNodes({ return ( <> - {nodes.map((node) => { - const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin).positionAbsolute; - const color = nodeColor === undefined ? undefined : nodeColorFunc(node); - const strokeColor = nodeStrokeColor === undefined ? undefined : nodeStrokeColorFunc(node); - - return ( - - ); - })} + {nodes.map((nodeId) => ( + + ))} ); } +const NodeComponentWrapper = memo(function NodeComponentWrapper({ + id, + nodeOrigin, + nodeColorFunc, + nodeStrokeColorFunc, + nodeClassNameFunc, + nodeBorderRadius, + nodeStrokeWidth, + shapeRendering, + NodeComponent, + onClick, +}: { + id: string; + nodeOrigin: NodeOrigin; + nodeColorFunc: GetMiniMapNodeAttribute; + nodeStrokeColorFunc: GetMiniMapNodeAttribute; + nodeClassNameFunc: GetMiniMapNodeAttribute; + nodeBorderRadius: number; + nodeStrokeWidth?: number; + NodeComponent: ComponentType; + onClick: MiniMapNodesProps['onClick']; + shapeRendering: string; +}) { + const node = useStore((s) => s.nodeLookup.get(id)); + if (!node) { + return null; + } + + const { x, y } = getNodePositionWithOrigin(node, node.origin || nodeOrigin).positionAbsolute; + + return ( + + ); +}); + export default memo(MiniMapNodes);