From 3c8720a5cf528d840f6fc3d8d2fb524b3973d95c Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 18 Jul 2022 12:52:17 +0200 Subject: [PATCH] refactor(onConnect): use onConnect handlers from store #2230 --- example/src/Validation/index.tsx | 37 ++++++++++++++------- src/components/Edges/wrapEdge.tsx | 31 +++++++----------- src/components/Handle/handler.ts | 53 ++++++++++++++++--------------- src/components/Handle/index.tsx | 40 +++++------------------ 4 files changed, 73 insertions(+), 88 deletions(-) diff --git a/example/src/Validation/index.tsx b/example/src/Validation/index.tsx index ba58b0b5..d2bf7b12 100644 --- a/example/src/Validation/index.tsx +++ b/example/src/Validation/index.tsx @@ -1,4 +1,4 @@ -import { MouseEvent as ReactMouseEvent, FC } from 'react'; +import { FC, useCallback, useState } from 'react'; import ReactFlow, { addEdge, Handle, @@ -6,11 +6,11 @@ import ReactFlow, { Position, Node, Edge, - OnConnectStartParams, NodeProps, NodeTypes, useNodesState, useEdgesState, + OnConnectStartParams, } from 'react-flow-renderer'; import './validation.css'; @@ -23,10 +23,6 @@ const initialNodes: Node[] = [ ]; const isValidConnection = (connection: Connection) => connection.target === 'B'; -const onConnectStart = (_: ReactMouseEvent, { nodeId, handleType }: OnConnectStartParams) => - console.log('on connect start', { nodeId, handleType }); -const onConnectStop = (event: MouseEvent) => console.log('on connect stop', event); -const onConnectEnd = (event: MouseEvent) => console.log('on connect end', event); const CustomInput: FC = () => ( <> @@ -49,13 +45,33 @@ const nodeTypes: NodeTypes = { }; const ValidationFlow = () => { + const [value, setValue] = useState(0); const [nodes, , onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState([]); - const onConnect = (params: Connection | Edge) => { - console.log('on connect', params); - setEdges((eds) => addEdge(params, eds)); - }; + const onConnectStart = useCallback( + (event: React.MouseEvent, params: OnConnectStartParams) => { + console.log('on connect start', params, event, value); + setValue(1); + }, + [value] + ); + + const onConnect = useCallback( + (params: Connection | Edge) => { + console.log('on connect', params); + setEdges((eds) => addEdge(params, eds)); + }, + [setEdges] + ); + + const onConnectEnd = useCallback( + (event: MouseEvent) => { + console.log('on connect end', event, value); + setValue(0); + }, + [value] + ); return ( { className="validationflow" nodeTypes={nodeTypes} onConnectStart={onConnectStart} - onConnectStop={onConnectStop} onConnectEnd={onConnectEnd} fitView /> diff --git a/src/components/Edges/wrapEdge.tsx b/src/components/Edges/wrapEdge.tsx index 4bc74835..4062565d 100644 --- a/src/components/Edges/wrapEdge.tsx +++ b/src/components/Edges/wrapEdge.tsx @@ -1,19 +1,13 @@ import React, { memo, ComponentType, useState, useMemo } from 'react'; import cc from 'classcat'; -import shallow from 'zustand/shallow'; -import { useStore, useStoreApi } from '../../store'; -import { EdgeProps, WrapEdgeProps, ReactFlowState, Connection } from '../../types'; +import { useStoreApi } from '../../store'; +import { EdgeProps, WrapEdgeProps, Connection } from '../../types'; import { handleMouseDown } from '../../components/Handle/handler'; import { EdgeAnchor } from './EdgeAnchor'; import { getMarkerId } from '../../utils/graph'; import { getMouseHandler } from './utils'; -const selector = (s: ReactFlowState) => ({ - addSelectedEdges: s.addSelectedEdges, - connectionMode: s.connectionMode, -}); - export default (EdgeComponent: ComponentType) => { const EdgeWrapper = ({ id, @@ -56,11 +50,11 @@ export default (EdgeComponent: ComponentType) => { rfId, }: WrapEdgeProps): JSX.Element | null => { const [updating, setUpdating] = useState(false); - const { addSelectedEdges, connectionMode } = useStore(selector, shallow); const store = useStoreApi(); const onEdgeClick = (event: React.MouseEvent): void => { - const edge = store.getState().edges.find((e) => e.id === id)!; + const { edges, addSelectedEdges } = store.getState(); + const edge = edges.find((e) => e.id === id)!; if (elementsSelectable) { store.setState({ nodesSelectionActive: false }); @@ -86,7 +80,7 @@ export default (EdgeComponent: ComponentType) => { onEdgeUpdateStart?.(event, edge, handleType); - const _onEdgeUpdate = onEdgeUpdateEnd + const _onEdgeUpdateEnd = onEdgeUpdateEnd ? (evt: MouseEvent): void => onEdgeUpdateEnd(evt, edge, handleType) : undefined; @@ -99,19 +93,18 @@ export default (EdgeComponent: ComponentType) => { } }; - handleMouseDown( + handleMouseDown({ event, handleId, nodeId, - store.setState, - onConnectEdge, + onConnect: onConnectEdge, isTarget, + getState: store.getState, + setState: store.setState, isValidConnection, - connectionMode, - handleType, - _onEdgeUpdate, - store.getState - ); + elementEdgeUpdaterType: handleType, + onEdgeUpdateEnd: _onEdgeUpdateEnd, + }); }; const onEdgeUpdaterSourceMouseDown = (event: React.MouseEvent): void => diff --git a/src/components/Handle/handler.ts b/src/components/Handle/handler.ts index 9c908ece..6e03da96 100644 --- a/src/components/Handle/handler.ts +++ b/src/components/Handle/handler.ts @@ -1,17 +1,8 @@ import { MouseEvent as ReactMouseEvent } from 'react'; -import { SetState } from 'zustand'; +import { GetState, SetState } from 'zustand'; import { getHostForElement } from '../../utils'; -import { - OnConnect, - OnConnectStart, - OnConnectStop, - OnConnectEnd, - ConnectionMode, - Connection, - HandleType, - ReactFlowState, -} from '../../types'; +import { OnConnect, ConnectionMode, Connection, HandleType, ReactFlowState } from '../../types'; type ValidConnectionFunc = (connection: Connection) => boolean; @@ -83,21 +74,29 @@ function resetRecentHandle(hoveredHandle: Element): void { hoveredHandle?.classList.remove('react-flow__handle-connecting'); } -export function handleMouseDown( - event: ReactMouseEvent, - handleId: string | null, - nodeId: string, - setState: SetState, - onConnect: OnConnect, - isTarget: boolean, - isValidConnection: ValidConnectionFunc, - connectionMode: ConnectionMode, - elementEdgeUpdaterType?: HandleType, - onEdgeUpdateEnd?: (evt: MouseEvent) => void, - onConnectStart?: OnConnectStart, - onConnectStop?: OnConnectStop, - onConnectEnd?: OnConnectEnd -): void { +export function handleMouseDown({ + event, + handleId, + nodeId, + onConnect, + isTarget, + getState, + setState, + isValidConnection, + elementEdgeUpdaterType, + onEdgeUpdateEnd, +}: { + event: ReactMouseEvent; + handleId: string | null; + nodeId: string; + onConnect: OnConnect; + isTarget: boolean; + getState: GetState; + setState: SetState; + isValidConnection: ValidConnectionFunc; + elementEdgeUpdaterType?: HandleType; + onEdgeUpdateEnd?: (evt: MouseEvent) => void; +}): void { const reactFlowNode = (event.target as Element).closest('.react-flow'); // when react-flow is used inside a shadow root we can't use document const doc = getHostForElement(event.target as HTMLElement); @@ -114,6 +113,7 @@ export function handleMouseDown( return; } + const { onConnectStart, connectionMode } = getState(); const handleType = elementEdgeUpdaterType ? elementEdgeUpdaterType : elementBelowIsTarget ? 'target' : 'source'; const containerBounds = reactFlowNode.getBoundingClientRect(); let recentHoveredHandle: Element; @@ -160,6 +160,7 @@ export function handleMouseDown( } function onMouseUp(event: MouseEvent) { + const { onConnectStop, onConnectEnd } = getState(); const { connection, isValid } = checkElementBelowIsValid( event, connectionMode, diff --git a/src/components/Handle/index.tsx b/src/components/Handle/index.tsx index 1bdb973d..88bf294f 100644 --- a/src/components/Handle/index.tsx +++ b/src/components/Handle/index.tsx @@ -14,14 +14,6 @@ const alwaysValid = () => true; export type HandleComponentProps = HandleProps & Omit, 'id'>; const selector = (s: ReactFlowState) => ({ - onConnectAction: s.onConnect, - onConnectStart: s.onConnectStart, - onConnectStop: s.onConnectStop, - onConnectEnd: s.onConnectEnd, - onClickConnectStart: s.onClickConnectStart, - onClickConnectStop: s.onClickConnectStop, - onClickConnectEnd: s.onClickConnectEnd, - connectionMode: s.connectionMode, connectionStartHandle: s.connectionStartHandle, connectOnClick: s.connectOnClick, hasDefaultEdges: s.hasDefaultEdges, @@ -45,25 +37,13 @@ const Handle = forwardRef( ) => { const store = useStoreApi(); const nodeId = useContext(NodeIdContext) as string; - const { - onConnectAction, - onConnectStart, - onConnectStop, - onConnectEnd, - onClickConnectStart, - onClickConnectStop, - onClickConnectEnd, - connectionMode, - connectionStartHandle, - connectOnClick, - hasDefaultEdges, - } = useStore(selector, shallow); + const { connectionStartHandle, connectOnClick, hasDefaultEdges } = useStore(selector, shallow); const handleId = id || null; const isTarget = type === 'target'; const onConnectExtended = (params: Connection) => { - const { defaultEdgeOptions } = store.getState(); + const { defaultEdgeOptions, onConnect: onConnectAction } = store.getState(); const edgeParams = { ...defaultEdgeOptions, @@ -80,26 +60,22 @@ const Handle = forwardRef( const onMouseDownHandler = (event: React.MouseEvent) => { if (event.button === 0) { - handleMouseDown( + handleMouseDown({ event, handleId, nodeId, - store.setState, - onConnectExtended, + onConnect: onConnectExtended, isTarget, + getState: store.getState, + setState: store.setState, isValidConnection, - connectionMode, - undefined, - undefined, - onConnectStart, - onConnectStop, - onConnectEnd - ); + }); } onMouseDown?.(event); }; const onClick = (event: React.MouseEvent) => { + const { onClickConnectStart, onClickConnectStop, onClickConnectEnd, connectionMode } = store.getState(); if (!connectionStartHandle) { onClickConnectStart?.(event, { nodeId, handleId, handleType: type }); store.setState({ connectionStartHandle: { nodeId, type, handleId } });