From 3170f875e543d81c90ebe4eb2a3ff9dda65340d7 Mon Sep 17 00:00:00 2001 From: GeoffreyLiu Date: Fri, 11 Nov 2022 09:31:53 +0800 Subject: [PATCH] refactor: access edge-label-renderer by storing the root element --- .../components/EdgeLabelRenderer/index.tsx | 21 ++++++++++++------- .../src/components/StoreUpdater/index.tsx | 14 +++++++++++-- packages/core/src/constants/component.ts | 1 + .../core/src/container/GraphView/index.tsx | 4 ++-- .../core/src/container/ReactFlow/index.tsx | 20 ++++++++++++++++-- packages/core/src/store/initialState.ts | 1 + packages/core/src/types/general.ts | 5 ++++- packages/core/src/utils/graph.ts | 3 --- 8 files changed, 52 insertions(+), 17 deletions(-) create mode 100644 packages/core/src/constants/component.ts diff --git a/packages/core/src/components/EdgeLabelRenderer/index.tsx b/packages/core/src/components/EdgeLabelRenderer/index.tsx index 772a8372..815916f0 100644 --- a/packages/core/src/components/EdgeLabelRenderer/index.tsx +++ b/packages/core/src/components/EdgeLabelRenderer/index.tsx @@ -1,19 +1,26 @@ -import { useRef } from 'react'; import type { ReactNode } from 'react'; import { createPortal } from 'react-dom'; import { useStoreApi } from '../../hooks/useStore'; -import { getEdgeLabelRendererId } from '../../utils/graph'; +import { EDGE_LABEL_RENDERER_MAIN_CLASS } from '../../constants/component'; function EdgeLabelRenderer({ children }: { children: ReactNode }) { - const store = useStoreApi() - const state = store.getState() - const wrapperRef = useRef(document.getElementById(getEdgeLabelRendererId(state.rfId))); + const store = useStoreApi(); + const { + rootElementRef: { current: rootElement }, + } = store.getState(); - if (!wrapperRef.current) { + if (!rootElement) { return null; } - return createPortal(children, wrapperRef.current); + const collection = rootElement.getElementsByClassName(EDGE_LABEL_RENDERER_MAIN_CLASS); + + const edgeLabelRendererElement = collection.item(0); + if (!edgeLabelRendererElement) { + return null; + } + + return createPortal(children, edgeLabelRendererElement); } export default EdgeLabelRenderer; diff --git a/packages/core/src/components/StoreUpdater/index.tsx b/packages/core/src/components/StoreUpdater/index.tsx index 2f98a453..bb3f89ca 100644 --- a/packages/core/src/components/StoreUpdater/index.tsx +++ b/packages/core/src/components/StoreUpdater/index.tsx @@ -3,7 +3,15 @@ import { StoreApi } from 'zustand'; import shallow from 'zustand/shallow'; import { useStore, useStoreApi } from '../../hooks/useStore'; -import type { Node, Edge, ReactFlowState, CoordinateExtent, ReactFlowProps, ReactFlowStore } from '../../types'; +import type { + Node, + Edge, + ReactFlowState, + CoordinateExtent, + ReactFlowProps, + ReactFlowStore, + RootElementRef, +} from '../../types'; type StoreUpdaterProps = Pick< ReactFlowProps, @@ -44,7 +52,7 @@ type StoreUpdaterProps = Pick< | 'onSelectionDragStop' | 'noPanClassName' | 'nodeOrigin' -> & { rfId: string }; +> & { rfId: string; rootElementRef: RootElementRef }; const selector = (s: ReactFlowState) => ({ setNodes: s.setNodes, @@ -117,6 +125,7 @@ const StoreUpdater = ({ noPanClassName, nodeOrigin, rfId, + rootElementRef, }: StoreUpdaterProps) => { const { setNodes, @@ -169,6 +178,7 @@ const StoreUpdater = ({ useDirectStoreUpdater('noPanClassName', noPanClassName, store.setState); useDirectStoreUpdater('nodeOrigin', nodeOrigin, store.setState); useDirectStoreUpdater('rfId', rfId, store.setState); + useDirectStoreUpdater('rootElementRef', rootElementRef, store.setState); useStoreUpdater(nodes, setNodes); useStoreUpdater(edges, setEdges); diff --git a/packages/core/src/constants/component.ts b/packages/core/src/constants/component.ts new file mode 100644 index 00000000..abb2f46b --- /dev/null +++ b/packages/core/src/constants/component.ts @@ -0,0 +1 @@ +export const EDGE_LABEL_RENDERER_MAIN_CLASS = 'react-flow__edgelabel-renderer' diff --git a/packages/core/src/container/GraphView/index.tsx b/packages/core/src/container/GraphView/index.tsx index 47be5bfc..98f9bede 100644 --- a/packages/core/src/container/GraphView/index.tsx +++ b/packages/core/src/container/GraphView/index.tsx @@ -6,7 +6,7 @@ import EdgeRenderer from '../EdgeRenderer'; import ViewportWrapper from '../Viewport'; import useOnInitHandler from '../../hooks/useOnInitHandler'; import type { EdgeTypesWrapped, NodeTypesWrapped, ReactFlowProps } from '../../types'; -import { getEdgeLabelRendererId } from '../../utils/graph'; +import { EDGE_LABEL_RENDERER_MAIN_CLASS } from '../../constants/component'; export type GraphViewProps = Omit & Required< @@ -159,7 +159,7 @@ const GraphView = ({ disableKeyboardA11y={disableKeyboardA11y} rfId={rfId} /> -
+
( const edgeTypesWrapped = useNodeOrEdgeTypes(edgeTypes, createEdgeTypes) as EdgeTypesWrapped; const rfId = id || '1'; + const rootElementRef = useRef(null); + + function setRootRef(element: HTMLDivElement | null) { + rootElementRef.current = element; + + if (typeof ref === 'function') { + ref(element); + return; + } + + if (ref) { + ref.current = element; + } + } + return (
( noPanClassName={noPanClassName} nodeOrigin={nodeOrigin} rfId={rfId} + rootElementRef={rootElementRef} /> {children} diff --git a/packages/core/src/store/initialState.ts b/packages/core/src/store/initialState.ts index ab918e65..a0353868 100644 --- a/packages/core/src/store/initialState.ts +++ b/packages/core/src/store/initialState.ts @@ -54,6 +54,7 @@ const initialState: ReactFlowStore = { connectOnClick: true, ariaLiveMessage: '', + rootElementRef: { current: null } }; export default initialState; diff --git a/packages/core/src/types/general.ts b/packages/core/src/types/general.ts index b18f4d32..48222f49 100644 --- a/packages/core/src/types/general.ts +++ b/packages/core/src/types/general.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import type { MouseEvent as ReactMouseEvent, ComponentType, MemoExoticComponent } from 'react'; +import type { MouseEvent as ReactMouseEvent, ComponentType, MemoExoticComponent, MutableRefObject } from 'react'; import type { Selection as D3Selection, ZoomBehavior } from 'd3'; import type { XYPosition, Rect, Transform, CoordinateExtent } from './utils'; @@ -129,6 +129,8 @@ export type ViewportHelperFunctions = { viewportInitialized: boolean; }; +export type RootElementRef = MutableRefObject + export type ReactFlowStore = { rfId: string; width: number; @@ -208,6 +210,7 @@ export type ReactFlowStore = { onSelectionChange?: OnSelectionChangeFunc; ariaLiveMessage: string; + rootElementRef: RootElementRef }; export type ReactFlowActions = { diff --git a/packages/core/src/utils/graph.ts b/packages/core/src/utils/graph.ts index 95feec38..5e7e776b 100644 --- a/packages/core/src/utils/graph.ts +++ b/packages/core/src/utils/graph.ts @@ -224,6 +224,3 @@ export const getD3Transition = (selection: D3Selection