refactor(wrapEdge): remove unnecessary memoization
This commit is contained in:
@@ -9,7 +9,6 @@ import ReactFlow, {
|
|||||||
MarkerType,
|
MarkerType,
|
||||||
MiniMap,
|
MiniMap,
|
||||||
Node,
|
Node,
|
||||||
Position,
|
|
||||||
ReactFlowInstance,
|
ReactFlowInstance,
|
||||||
useEdgesState,
|
useEdgesState,
|
||||||
useNodesState,
|
useNodesState,
|
||||||
@@ -20,6 +19,11 @@ import CustomEdge2 from './CustomEdge2';
|
|||||||
const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitView();
|
||||||
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
const onNodeDragStop = (_: MouseEvent, node: Node) => console.log('drag stop', node);
|
||||||
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
const onNodeClick = (_: MouseEvent, node: Node) => console.log('click', node);
|
||||||
|
const onEdgeClick = (_: MouseEvent, edge: Edge) => console.log('click', edge);
|
||||||
|
const onEdgeDoubleClick = (_: MouseEvent, edge: Edge) => console.log('dblclick', edge);
|
||||||
|
const onEdgeMouseEnter = (_: MouseEvent, edge: Edge) => console.log('enter', edge);
|
||||||
|
const onEdgeMouseMove = (_: MouseEvent, edge: Edge) => console.log('move', edge);
|
||||||
|
const onEdgeMouseLeave = (_: MouseEvent, edge: Edge) => console.log('leave', edge);
|
||||||
|
|
||||||
const initialNodes: Node[] = [
|
const initialNodes: Node[] = [
|
||||||
{ id: '1', type: 'input', data: { label: 'Input 1' }, position: { x: 250, y: 0 } },
|
{ id: '1', type: 'input', data: { label: 'Input 1' }, position: { x: 250, y: 0 } },
|
||||||
@@ -131,6 +135,11 @@ const EdgesFlow = () => {
|
|||||||
onInit={onInit}
|
onInit={onInit}
|
||||||
snapToGrid={true}
|
snapToGrid={true}
|
||||||
edgeTypes={edgeTypes}
|
edgeTypes={edgeTypes}
|
||||||
|
onEdgeClick={onEdgeClick}
|
||||||
|
onEdgeDoubleClick={onEdgeDoubleClick}
|
||||||
|
onEdgeMouseEnter={onEdgeMouseEnter}
|
||||||
|
onEdgeMouseMove={onEdgeMouseMove}
|
||||||
|
onEdgeMouseLeave={onEdgeMouseLeave}
|
||||||
>
|
>
|
||||||
<MiniMap />
|
<MiniMap />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
import { MarkerType, Position } from '../../types';
|
import { MouseEvent as ReactMouseEvent } from 'react';
|
||||||
|
import { GetState } from 'zustand';
|
||||||
|
|
||||||
|
import { Edge, MarkerType, Position, ReactFlowState } from '../../types';
|
||||||
|
|
||||||
export const getMarkerEnd = (markerType?: MarkerType, markerEndId?: string): string => {
|
export const getMarkerEnd = (markerType?: MarkerType, markerEndId?: string): string => {
|
||||||
if (typeof markerEndId !== 'undefined' && markerEndId) {
|
if (typeof markerEndId !== 'undefined' && markerEndId) {
|
||||||
@@ -52,3 +55,16 @@ export const getCenter = ({
|
|||||||
|
|
||||||
return [centerX, centerY, xOffset, yOffset];
|
return [centerX, centerY, xOffset, yOffset];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function getMouseHandler(
|
||||||
|
id: string,
|
||||||
|
getState: GetState<ReactFlowState>,
|
||||||
|
handler?: (event: ReactMouseEvent<SVGGElement, MouseEvent>, edge: Edge) => void
|
||||||
|
) {
|
||||||
|
return handler === undefined
|
||||||
|
? handler
|
||||||
|
: (event: ReactMouseEvent<SVGGElement, MouseEvent>) => {
|
||||||
|
const edge = getState().edges.find((e) => e.id === id)!;
|
||||||
|
handler(event, { ...edge });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import React, { memo, ComponentType, useCallback, useState, useMemo } from 'react';
|
import React, { memo, ComponentType, useState, useMemo } from 'react';
|
||||||
import cc from 'classcat';
|
import cc from 'classcat';
|
||||||
import shallow from 'zustand/shallow';
|
import shallow from 'zustand/shallow';
|
||||||
|
|
||||||
import { useStore, useStoreApi } from '../../store';
|
import { useStore, useStoreApi } from '../../store';
|
||||||
import { Edge, EdgeProps, WrapEdgeProps, ReactFlowState, Connection } from '../../types';
|
import { EdgeProps, WrapEdgeProps, ReactFlowState, Connection } from '../../types';
|
||||||
import { handleMouseDown } from '../../components/Handle/handler';
|
import { handleMouseDown } from '../../components/Handle/handler';
|
||||||
import { EdgeAnchor } from './EdgeAnchor';
|
import { EdgeAnchor } from './EdgeAnchor';
|
||||||
import { getMarkerId } from '../../utils/graph';
|
import { getMarkerId } from '../../utils/graph';
|
||||||
|
import { getMouseHandler } from './utils';
|
||||||
|
|
||||||
const selector = (s: ReactFlowState) => ({
|
const selector = (s: ReactFlowState) => ({
|
||||||
addSelectedEdges: s.addSelectedEdges,
|
addSelectedEdges: s.addSelectedEdges,
|
||||||
@@ -53,10 +54,78 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
markerEnd,
|
markerEnd,
|
||||||
markerStart,
|
markerStart,
|
||||||
}: WrapEdgeProps): JSX.Element | null => {
|
}: WrapEdgeProps): JSX.Element | null => {
|
||||||
const store = useStoreApi();
|
|
||||||
const { addSelectedEdges, connectionMode } = useStore(selector, shallow);
|
|
||||||
|
|
||||||
const [updating, setUpdating] = useState<boolean>(false);
|
const [updating, setUpdating] = useState<boolean>(false);
|
||||||
|
const { addSelectedEdges, connectionMode } = useStore(selector, shallow);
|
||||||
|
const store = useStoreApi();
|
||||||
|
|
||||||
|
const onEdgeClick = (event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
||||||
|
const edge = store.getState().edges.find((e) => e.id === id)!;
|
||||||
|
|
||||||
|
if (elementsSelectable) {
|
||||||
|
store.setState({ nodesSelectionActive: false });
|
||||||
|
addSelectedEdges([id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
onClick?.(event, edge);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEdgeDoubleClickHandler = getMouseHandler(id, store.getState, onEdgeDoubleClick);
|
||||||
|
const onEdgeContextMenu = getMouseHandler(id, store.getState, onContextMenu);
|
||||||
|
const onEdgeMouseEnter = getMouseHandler(id, store.getState, onMouseEnter);
|
||||||
|
const onEdgeMouseMove = getMouseHandler(id, store.getState, onMouseMove);
|
||||||
|
const onEdgeMouseLeave = getMouseHandler(id, store.getState, onMouseLeave);
|
||||||
|
|
||||||
|
const handleEdgeUpdater = (event: React.MouseEvent<SVGGElement, MouseEvent>, isSourceHandle: boolean) => {
|
||||||
|
const nodeId = isSourceHandle ? target : source;
|
||||||
|
const handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null;
|
||||||
|
const handleType = isSourceHandle ? 'target' : 'source';
|
||||||
|
const isValidConnection = () => true;
|
||||||
|
const isTarget = isSourceHandle;
|
||||||
|
const edge = store.getState().edges.find((e) => e.id === id)!;
|
||||||
|
|
||||||
|
onEdgeUpdateStart?.(event, edge, handleType);
|
||||||
|
|
||||||
|
const _onEdgeUpdate = onEdgeUpdateEnd
|
||||||
|
? (evt: MouseEvent): void => onEdgeUpdateEnd(evt, edge, handleType)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const onConnectEdge = (connection: Connection) => {
|
||||||
|
const { edges } = store.getState();
|
||||||
|
const edge = edges.find((e) => e.id === id);
|
||||||
|
|
||||||
|
if (edge && onEdgeUpdate) {
|
||||||
|
onEdgeUpdate(edge, connection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
handleMouseDown(
|
||||||
|
event,
|
||||||
|
handleId,
|
||||||
|
nodeId,
|
||||||
|
store.setState,
|
||||||
|
onConnectEdge,
|
||||||
|
isTarget,
|
||||||
|
isValidConnection,
|
||||||
|
connectionMode,
|
||||||
|
handleType,
|
||||||
|
_onEdgeUpdate,
|
||||||
|
store.getState
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onEdgeUpdaterSourceMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void =>
|
||||||
|
handleEdgeUpdater(event, true);
|
||||||
|
const onEdgeUpdaterTargetMouseDown = (event: React.MouseEvent<SVGGElement, MouseEvent>): void =>
|
||||||
|
handleEdgeUpdater(event, false);
|
||||||
|
|
||||||
|
const onEdgeUpdaterMouseEnter = () => setUpdating(true);
|
||||||
|
const onEdgeUpdaterMouseOut = () => setUpdating(false);
|
||||||
|
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart)})`, [markerStart]);
|
||||||
|
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd)})`, [markerEnd]);
|
||||||
|
|
||||||
|
if (hidden) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const inactive = !elementsSelectable && !onClick;
|
const inactive = !elementsSelectable && !onClick;
|
||||||
const handleEdgeUpdate = typeof onEdgeUpdate !== 'undefined';
|
const handleEdgeUpdate = typeof onEdgeUpdate !== 'undefined';
|
||||||
@@ -67,139 +136,6 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
|
|||||||
{ selected, animated, inactive, updating },
|
{ selected, animated, inactive, updating },
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const edgeElement = useMemo<Edge>(() => {
|
|
||||||
const el: Edge = {
|
|
||||||
id,
|
|
||||||
source,
|
|
||||||
target,
|
|
||||||
type,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (sourceHandleId) {
|
|
||||||
el.sourceHandle = sourceHandleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetHandleId) {
|
|
||||||
el.targetHandle = targetHandleId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data !== 'undefined') {
|
|
||||||
el.data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return el;
|
|
||||||
}, [id, source, target, type, sourceHandleId, targetHandleId, data]);
|
|
||||||
|
|
||||||
const onEdgeClick = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
|
||||||
if (elementsSelectable) {
|
|
||||||
store.setState({ nodesSelectionActive: false });
|
|
||||||
addSelectedEdges([edgeElement.id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
onClick?.(event, edgeElement);
|
|
||||||
},
|
|
||||||
[elementsSelectable, edgeElement, onClick]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeDoubleClickHandler = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>) => {
|
|
||||||
onEdgeDoubleClick?.(event, edgeElement);
|
|
||||||
},
|
|
||||||
[edgeElement, onEdgeDoubleClick]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeContextMenu = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
|
||||||
onContextMenu?.(event, edgeElement);
|
|
||||||
},
|
|
||||||
[edgeElement, onContextMenu]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeMouseEnter = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
|
||||||
onMouseEnter?.(event, edgeElement);
|
|
||||||
},
|
|
||||||
[edgeElement, onContextMenu]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeMouseMove = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
|
||||||
onMouseMove?.(event, edgeElement);
|
|
||||||
},
|
|
||||||
[edgeElement, onContextMenu]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeMouseLeave = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
|
||||||
onMouseLeave?.(event, edgeElement);
|
|
||||||
},
|
|
||||||
[edgeElement, onContextMenu]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleEdgeUpdater = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>, isSourceHandle: boolean) => {
|
|
||||||
const nodeId = isSourceHandle ? target : source;
|
|
||||||
const handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null;
|
|
||||||
const handleType = isSourceHandle ? 'target' : 'source';
|
|
||||||
const isValidConnection = () => true;
|
|
||||||
const isTarget = isSourceHandle;
|
|
||||||
|
|
||||||
onEdgeUpdateStart?.(event, edgeElement, handleType);
|
|
||||||
|
|
||||||
const _onEdgeUpdate = onEdgeUpdateEnd
|
|
||||||
? (evt: MouseEvent): void => onEdgeUpdateEnd(evt, edgeElement, handleType)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const onConnectEdge = (connection: Connection) => {
|
|
||||||
const { edges } = store.getState();
|
|
||||||
const edge = edges.find((e) => e.id === id);
|
|
||||||
|
|
||||||
if (edge && onEdgeUpdate) {
|
|
||||||
onEdgeUpdate(edge, connection);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
handleMouseDown(
|
|
||||||
event,
|
|
||||||
handleId,
|
|
||||||
nodeId,
|
|
||||||
store.setState,
|
|
||||||
onConnectEdge,
|
|
||||||
isTarget,
|
|
||||||
isValidConnection,
|
|
||||||
connectionMode,
|
|
||||||
handleType,
|
|
||||||
_onEdgeUpdate,
|
|
||||||
store.getState
|
|
||||||
);
|
|
||||||
},
|
|
||||||
[id, source, target, type, sourceHandleId, targetHandleId, edgeElement, onEdgeUpdate]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeUpdaterSourceMouseDown = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
|
||||||
handleEdgeUpdater(event, true);
|
|
||||||
},
|
|
||||||
[id, source, sourceHandleId, handleEdgeUpdater]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeUpdaterTargetMouseDown = useCallback(
|
|
||||||
(event: React.MouseEvent<SVGGElement, MouseEvent>): void => {
|
|
||||||
handleEdgeUpdater(event, false);
|
|
||||||
},
|
|
||||||
[id, target, targetHandleId, handleEdgeUpdater]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onEdgeUpdaterMouseEnter = useCallback(() => setUpdating(true), [setUpdating]);
|
|
||||||
const onEdgeUpdaterMouseOut = useCallback(() => setUpdating(false), [setUpdating]);
|
|
||||||
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart)})`, [markerStart]);
|
|
||||||
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd)})`, [markerEnd]);
|
|
||||||
|
|
||||||
if (hidden) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<g
|
<g
|
||||||
className={edgeClasses}
|
className={edgeClasses}
|
||||||
|
|||||||
Reference in New Issue
Block a user