refactor(markers): optimze marker creation, pass ids closes #2188

This commit is contained in:
moklick
2022-06-21 17:15:58 +02:00
parent f52ab12f57
commit 3d74b519b5
10 changed files with 82 additions and 43 deletions
@@ -1,4 +1,4 @@
import React, { useMemo } from 'react';
import React, { memo, useCallback } from 'react';
import { useStore } from '../../store';
import { EdgeMarker, ReactFlowState } from '../../types';
@@ -9,6 +9,7 @@ interface MarkerProps extends EdgeMarker {
}
interface MarkerDefinitionsProps {
defaultColor: string;
rfId?: string;
}
const Marker = ({
@@ -40,26 +41,36 @@ const Marker = ({
);
};
const edgesSelector = (s: ReactFlowState) => s.edges;
const MarkerDefinitions = ({ defaultColor }: MarkerDefinitionsProps) => {
const edges = useStore(edgesSelector);
const markers = useMemo(() => {
const markerSelector =
({ defaultColor, rfId }: { defaultColor: string; rfId?: string }) =>
(s: ReactFlowState) => {
const ids: string[] = [];
return edges.reduce<MarkerProps[]>((markers, edge) => {
[edge.markerStart, edge.markerEnd].forEach((marker) => {
if (marker && typeof marker === 'object') {
const markerId = getMarkerId(marker);
if (!ids.includes(markerId)) {
markers.push({ id: markerId, color: marker.color || defaultColor, ...marker });
ids.push(markerId);
return s.edges
.reduce<MarkerProps[]>((markers, edge) => {
[edge.markerStart, edge.markerEnd].forEach((marker) => {
if (marker && typeof marker === 'object') {
const markerId = getMarkerId(marker, rfId);
if (!ids.includes(markerId)) {
markers.push({ id: markerId, color: marker.color || defaultColor, ...marker });
ids.push(markerId);
}
}
}
});
return markers.sort((a, b) => a.id.localeCompare(b.id));
}, []);
}, [edges, defaultColor]);
});
return markers;
}, [])
.sort((a, b) => a.id.localeCompare(b.id));
};
// when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore
// when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper
// that we can then use for creating our unique marker ids
const MarkerDefinitions = ({ defaultColor, rfId }: MarkerDefinitionsProps) => {
const markers = useStore(
useCallback(markerSelector({ defaultColor, rfId }), [defaultColor, rfId]),
// the id includes all marker options, so we just need to look at that part of the marker
(a, b) => !(a.length !== b.length || a.some((m, i) => m.id !== b[i].id))
);
return (
<defs>
@@ -82,4 +93,4 @@ const MarkerDefinitions = ({ defaultColor }: MarkerDefinitionsProps) => {
MarkerDefinitions.displayName = 'MarkerDefinitions';
export default MarkerDefinitions;
export default memo(MarkerDefinitions);
+3 -1
View File
@@ -40,6 +40,7 @@ interface EdgeRendererProps {
edgeUpdaterRadius?: number;
noPanClassName?: string;
elevateEdgesOnSelect: boolean;
rfId?: string;
}
const selector = (s: ReactFlowState) => ({
@@ -93,7 +94,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
height={height}
className="react-flow__edges react-flow__container"
>
{isMaxLevel && <MarkerDefinitions defaultColor={defaultMarkerColor} />}
{isMaxLevel && <MarkerDefinitions defaultColor={defaultMarkerColor} rfId={props.rfId} />}
<g>
{edges.map((edge: Edge) => {
const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(nodeInternals, edge.source);
@@ -184,6 +185,7 @@ const EdgeRenderer = (props: EdgeRendererProps) => {
onEdgeDoubleClick={props.onEdgeDoubleClick}
onEdgeUpdateStart={props.onEdgeUpdateStart}
onEdgeUpdateEnd={props.onEdgeUpdateEnd}
rfId={props.rfId}
/>
);
})}
+2
View File
@@ -84,6 +84,7 @@ const GraphView = ({
noWheelClassName,
noPanClassName,
elevateEdgesOnSelect,
id,
}: GraphViewProps) => {
useOnInitHandler(onInit);
@@ -139,6 +140,7 @@ const GraphView = ({
defaultMarkerColor={defaultMarkerColor}
noPanClassName={noPanClassName}
elevateEdgesOnSelect={!!elevateEdgesOnSelect}
rfId={id}
/>
<NodeRenderer
nodeTypes={nodeTypes}
+1
View File
@@ -211,6 +211,7 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
noWheelClassName={noWheelClassName}
noPanClassName={noPanClassName}
elevateEdgesOnSelect={elevateEdgesOnSelect}
id={rest?.id}
/>
<StoreUpdater
nodes={nodes}