Merge pull request #4725 from xyflow/feat/use-handle-connection
add `useNodeConnections`, deprecate `useHandleConnections`
This commit is contained in:
@@ -22,6 +22,7 @@ type useHandleConnectionsParams = {
|
||||
* Hook to check if a <Handle /> is connected to another <Handle /> and get the connections.
|
||||
*
|
||||
* @public
|
||||
* @deprecated Use `useNodeConnections` instead.
|
||||
* @param param.type - handle type 'source' or 'target'
|
||||
* @param param.nodeId - node id - if not provided, the node id from the NodeIdContext is used
|
||||
* @param param.id - the handle id (this is only needed if the node has multiple handles of the same type)
|
||||
@@ -31,18 +32,22 @@ type useHandleConnectionsParams = {
|
||||
*/
|
||||
export function useHandleConnections({
|
||||
type,
|
||||
id = null,
|
||||
id,
|
||||
nodeId,
|
||||
onConnect,
|
||||
onDisconnect,
|
||||
}: useHandleConnectionsParams): HandleConnection[] {
|
||||
console.warn(
|
||||
'[DEPRECATED] `useHandleConnections` is deprecated. Instead use `useNodeConnections` https://reactflow.dev/api-reference/hooks/useNodeConnections'
|
||||
);
|
||||
|
||||
const _nodeId = useNodeId();
|
||||
const currentNodeId = nodeId ?? _nodeId;
|
||||
|
||||
const prevConnections = useRef<Map<string, HandleConnection> | null>(null);
|
||||
|
||||
const connections = useStore(
|
||||
(state) => state.connectionLookup.get(`${currentNodeId}-${type}-${id}`),
|
||||
(state) => state.connectionLookup.get(`${currentNodeId}-${type}${id ? `-${id}` : ''}`),
|
||||
areConnectionMapsEqual
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
import {
|
||||
Connection,
|
||||
NodeConnection,
|
||||
HandleType,
|
||||
areConnectionMapsEqual,
|
||||
handleConnectionChange,
|
||||
errorMessages,
|
||||
} from '@xyflow/system';
|
||||
|
||||
import { useStore } from './useStore';
|
||||
import { useNodeId } from '../contexts/NodeIdContext';
|
||||
|
||||
const error014 = errorMessages['error014']();
|
||||
|
||||
type UseNodeConnectionsParams = {
|
||||
type?: HandleType;
|
||||
handleId?: string;
|
||||
nodeId?: string;
|
||||
onConnect?: (connections: Connection[]) => void;
|
||||
onDisconnect?: (connections: Connection[]) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to retrieve all edges connected to a node. Can be filtered by handle type and id.
|
||||
*
|
||||
* @public
|
||||
* @param param.nodeId - node id - optional if called inside a custom node
|
||||
* @param param.type - filter by handle type 'source' or 'target'
|
||||
* @param param.handleId - filter by handle id (this is only needed if the node has multiple handles of the same type)
|
||||
* @param param.onConnect - gets called when a connection is established
|
||||
* @param param.onDisconnect - gets called when a connection is removed
|
||||
* @returns an array with connections
|
||||
*/
|
||||
export function useNodeConnections({
|
||||
type,
|
||||
handleId,
|
||||
nodeId,
|
||||
onConnect,
|
||||
onDisconnect,
|
||||
}: UseNodeConnectionsParams = {}): NodeConnection[] {
|
||||
const _nodeId = useNodeId();
|
||||
const currentNodeId = nodeId ?? _nodeId;
|
||||
|
||||
if (!currentNodeId) {
|
||||
throw new Error(error014);
|
||||
}
|
||||
|
||||
const prevConnections = useRef<Map<string, NodeConnection> | null>(null);
|
||||
|
||||
const connections = useStore(
|
||||
(state) =>
|
||||
state.connectionLookup.get(`${currentNodeId}${type ? (handleId ? `-${type}-${handleId}` : `-${type}`) : ''}`),
|
||||
areConnectionMapsEqual
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// @todo dicuss if onConnect/onDisconnect should be called when the component mounts/unmounts
|
||||
if (prevConnections.current && prevConnections.current !== connections) {
|
||||
const _connections = connections ?? new Map();
|
||||
handleConnectionChange(prevConnections.current, _connections, onDisconnect);
|
||||
handleConnectionChange(_connections, prevConnections.current, onConnect);
|
||||
}
|
||||
|
||||
prevConnections.current = connections ?? new Map();
|
||||
}, [connections, onConnect, onDisconnect]);
|
||||
|
||||
return useMemo(() => Array.from(connections?.values() ?? []), [connections]);
|
||||
}
|
||||
@@ -238,7 +238,14 @@ export function useReactFlow<NodeType extends Node = Node, EdgeType extends Edge
|
||||
Array.from(
|
||||
store
|
||||
.getState()
|
||||
.connectionLookup.get(`${nodeId}-${type}-${id ?? null}`)
|
||||
.connectionLookup.get(`${nodeId}-${type}${id ? `-${id}` : ''}`)
|
||||
?.values() ?? []
|
||||
),
|
||||
getNodeConnections: ({ type, handleId, nodeId }) =>
|
||||
Array.from(
|
||||
store
|
||||
.getState()
|
||||
.connectionLookup.get(`${nodeId}${type ? (handleId ? `-${type}-${handleId}` : `-${type}`) : ''}`)
|
||||
?.values() ?? []
|
||||
),
|
||||
};
|
||||
|
||||
@@ -24,6 +24,7 @@ export { useOnViewportChange, type UseOnViewportChangeOptions } from './hooks/us
|
||||
export { useOnSelectionChange, type UseOnSelectionChangeOptions } from './hooks/useOnSelectionChange';
|
||||
export { useNodesInitialized, type UseNodesInitializedOptions } from './hooks/useNodesInitialized';
|
||||
export { useHandleConnections } from './hooks/useHandleConnections';
|
||||
export { useNodeConnections } from './hooks/useNodeConnections';
|
||||
export { useNodesData } from './hooks/useNodesData';
|
||||
export { useConnection } from './hooks/useConnection';
|
||||
export { useInternalNode } from './hooks/useInternalNode';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-namespace */
|
||||
import type { HandleConnection, HandleType, Rect, Viewport } from '@xyflow/system';
|
||||
import type { HandleConnection, HandleType, NodeConnection, Rect, Viewport } from '@xyflow/system';
|
||||
import type { Node, Edge, ViewportHelperFunctions, InternalNode } from '.';
|
||||
|
||||
export type ReactFlowJsonObject<NodeType extends Node = Node, EdgeType extends Edge = Edge> = {
|
||||
@@ -183,7 +183,7 @@ export type GeneralHelpers<NodeType extends Node = Node, EdgeType extends Edge =
|
||||
getNodesBounds: (nodes: (NodeType | InternalNode | string)[]) => Rect;
|
||||
/**
|
||||
* Gets all connections for a given handle belonging to a specific node.
|
||||
*
|
||||
* @deprecated
|
||||
* @param type - handle type 'source' or 'target'
|
||||
* @param id - the handle id (this is only needed if you have multiple handles of the same type, meaning you have to provide a unique id for each handle)
|
||||
* @param nodeId - the node id the handle belongs to
|
||||
@@ -198,6 +198,23 @@ export type GeneralHelpers<NodeType extends Node = Node, EdgeType extends Edge =
|
||||
nodeId: string;
|
||||
id?: string | null;
|
||||
}) => HandleConnection[];
|
||||
/**
|
||||
* Gets all connections to a node. Can be filtered by handle type and id.
|
||||
* @deprecated use `getNodeConnections` instead
|
||||
* @param type - handle type 'source' or 'target'
|
||||
* @param handleId - the handle id (this is only needed if you have multiple handles of the same type, meaning you have to provide a unique id for each handle)
|
||||
* @param nodeId - the node id the handle belongs to
|
||||
* @returns an array with handle connections
|
||||
*/
|
||||
getNodeConnections: ({
|
||||
type,
|
||||
handleId,
|
||||
nodeId,
|
||||
}: {
|
||||
type?: HandleType;
|
||||
nodeId: string;
|
||||
handleId?: string | null;
|
||||
}) => NodeConnection[];
|
||||
};
|
||||
|
||||
export type ReactFlowInstance<NodeType extends Node = Node, EdgeType extends Edge = Edge> = GeneralHelpers<
|
||||
|
||||
Reference in New Issue
Block a user