diff --git a/examples/react/src/App/routes.ts b/examples/react/src/App/routes.ts
index 18307c79..4bab00f5 100644
--- a/examples/react/src/App/routes.ts
+++ b/examples/react/src/App/routes.ts
@@ -44,8 +44,9 @@ import CancelConnection from '../examples/CancelConnection';
import InteractiveMinimap from '../examples/InteractiveMinimap';
import UseOnSelectionChange from '../examples/UseOnSelectionChange';
import NodeToolbar from '../examples/NodeToolbar';
-import useNodesInitialized from '../examples/UseNodesInit';
-import useHandleConnectionStatus from '../examples/UseHandleConnectionStatus';
+import UseNodesInitialized from '../examples/UseNodesInit';
+import UseNodesData from '../examples/UseNodesData';
+import UseHandleConnections from '../examples/UseHandleConnections';
export interface IRoute {
name: string;
@@ -262,7 +263,7 @@ const routes: IRoute[] = [
{
name: 'useNodesInitialized',
path: 'use-nodes-initialized',
- component: useNodesInitialized,
+ component: UseNodesInitialized,
},
{
name: 'useOnSelectionChange',
@@ -275,9 +276,14 @@ const routes: IRoute[] = [
component: UseReactFlow,
},
{
- name: 'useHandleConnectionStatus',
- path: 'usehandleconnectionstatus',
- component: useHandleConnectionStatus,
+ name: 'useHandleConnections',
+ path: 'usehandleconnections',
+ component: UseHandleConnections,
+ },
+ {
+ name: 'useNodesData',
+ path: 'usenodesdata',
+ component: UseNodesData,
},
{
name: 'useUpdateNodeInternals',
diff --git a/examples/react/src/examples/UseHandleConnectionStatus/MultiHandleNode.tsx b/examples/react/src/examples/UseHandleConnections/MultiHandleNode.tsx
similarity index 82%
rename from examples/react/src/examples/UseHandleConnectionStatus/MultiHandleNode.tsx
rename to examples/react/src/examples/UseHandleConnections/MultiHandleNode.tsx
index f8a31143..e04f3448 100644
--- a/examples/react/src/examples/UseHandleConnectionStatus/MultiHandleNode.tsx
+++ b/examples/react/src/examples/UseHandleConnections/MultiHandleNode.tsx
@@ -1,6 +1,5 @@
import { memo, FC, useEffect, useCallback } from 'react';
-import { Handle, Position, NodeProps, useHandleConnectionStatus, Connection } from '@xyflow/react';
-import { HandleComponentProps } from '@xyflow/react/dist/esm/components/Handle';
+import { Handle, Position, NodeProps, useHandleConnections, Connection, HandleComponentProps } from '@xyflow/react';
function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeId: string }) {
const onConnect = useCallback(
@@ -12,7 +11,7 @@ function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeI
(connections: Connection[]) => console.log('onDisconnect handler, node id:', nodeId, connections),
[nodeId]
);
- const status = useHandleConnectionStatus({
+ const connections = useHandleConnections({
handleType: handleProps.type,
handleId: handleProps.id,
onConnect,
@@ -20,8 +19,8 @@ function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeI
});
useEffect(() => {
- console.log('useEffect, node id:', nodeId, handleProps.type, status);
- }, [status]);
+ console.log('useEffect, node id:', nodeId, handleProps.type, connections);
+ }, [connections]);
return ;
}
diff --git a/examples/react/src/examples/UseHandleConnectionStatus/SingleHandleNode.tsx b/examples/react/src/examples/UseHandleConnections/SingleHandleNode.tsx
similarity index 81%
rename from examples/react/src/examples/UseHandleConnectionStatus/SingleHandleNode.tsx
rename to examples/react/src/examples/UseHandleConnections/SingleHandleNode.tsx
index ebbe584c..444499fb 100644
--- a/examples/react/src/examples/UseHandleConnectionStatus/SingleHandleNode.tsx
+++ b/examples/react/src/examples/UseHandleConnections/SingleHandleNode.tsx
@@ -1,6 +1,5 @@
import { memo, FC, useEffect, useCallback } from 'react';
-import { Handle, Position, NodeProps, useHandleConnectionStatus, Connection } from '@xyflow/react';
-import { HandleComponentProps } from '@xyflow/react/dist/esm/components/Handle';
+import { Handle, Position, NodeProps, useHandleConnections, Connection, HandleComponentProps } from '@xyflow/react';
function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeId: string }) {
const onConnect = useCallback(
@@ -15,7 +14,7 @@ function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeI
},
[nodeId]
);
- const status = useHandleConnectionStatus({
+ const connections = useHandleConnections({
handleType: handleProps.type,
handleId: handleProps.id,
onConnect,
@@ -23,8 +22,8 @@ function CustomHandle({ nodeId, ...handleProps }: HandleComponentProps & { nodeI
});
useEffect(() => {
- console.log('useEffect, node id:', nodeId, handleProps.type, status);
- }, [status]);
+ console.log('useEffect, node id:', nodeId, handleProps.type, connections);
+ }, [connections]);
return ;
}
diff --git a/examples/react/src/examples/UseHandleConnectionStatus/index.tsx b/examples/react/src/examples/UseHandleConnections/index.tsx
similarity index 100%
rename from examples/react/src/examples/UseHandleConnectionStatus/index.tsx
rename to examples/react/src/examples/UseHandleConnections/index.tsx
diff --git a/examples/react/src/examples/UseNodesData/ResultNode.tsx b/examples/react/src/examples/UseNodesData/ResultNode.tsx
new file mode 100644
index 00000000..09603eac
--- /dev/null
+++ b/examples/react/src/examples/UseNodesData/ResultNode.tsx
@@ -0,0 +1,25 @@
+import { memo, useEffect } from 'react';
+import { Handle, Position, useHandleConnections, useNodesData } from '@xyflow/react';
+
+function ResultNode() {
+ const connections = useHandleConnections({
+ handleType: 'target',
+ });
+ const nodesData = useNodesData<{ text: string }>(connections.map((connection) => connection.source));
+
+ useEffect(() => {
+ console.log('incoming data changed', nodesData);
+ }, [nodesData]);
+
+ return (
+
+
+
+ incoming texts:{' '}
+ {nodesData?.filter((nodeData) => nodeData.text).map(({ text }, i) =>
{text}
) || 'none'}
+
+
+ );
+}
+
+export default memo(ResultNode);
diff --git a/examples/react/src/examples/UseNodesData/TextNode.tsx b/examples/react/src/examples/UseNodesData/TextNode.tsx
new file mode 100644
index 00000000..a7388cb0
--- /dev/null
+++ b/examples/react/src/examples/UseNodesData/TextNode.tsx
@@ -0,0 +1,20 @@
+import { memo, ChangeEventHandler } from 'react';
+import { Position, NodeProps, useUpdateNodeData, Handle } from '@xyflow/react';
+
+function TextNode({ id, data }: NodeProps) {
+ const updateNodeData = useUpdateNodeData();
+
+ const onChange: ChangeEventHandler = (evt) => updateNodeData(id, { text: evt.target.value });
+
+ return (
+
+ );
+}
+
+export default memo(TextNode);
diff --git a/examples/react/src/examples/UseNodesData/index.tsx b/examples/react/src/examples/UseNodesData/index.tsx
new file mode 100644
index 00000000..67e68a2f
--- /dev/null
+++ b/examples/react/src/examples/UseNodesData/index.tsx
@@ -0,0 +1,83 @@
+import { useCallback } from 'react';
+import {
+ ReactFlow,
+ Controls,
+ addEdge,
+ Connection,
+ useNodesState,
+ useEdgesState,
+ Background,
+ Node,
+ Edge,
+} from '@xyflow/react';
+
+import TextNode from './TextNode';
+import ResultNode from './ResultNode';
+
+const nodeTypes = {
+ text: TextNode,
+ result: ResultNode,
+};
+
+const initNodes: Node[] = [
+ {
+ id: '1',
+ type: 'text',
+ data: {
+ text: 'hello',
+ },
+ position: { x: 0, y: 0 },
+ },
+ {
+ id: '2',
+ type: 'text',
+ data: {
+ text: 'world',
+ },
+ position: { x: 0, y: 100 },
+ },
+
+ {
+ id: '3',
+ type: 'result',
+ data: {},
+ position: { x: 300, y: 50 },
+ },
+];
+
+const initEdges: Edge[] = [
+ {
+ id: 'e1-3',
+ source: '1',
+ target: '3',
+ },
+ {
+ id: 'e2-3',
+ source: '2',
+ target: '3',
+ },
+];
+
+const CustomNodeFlow = () => {
+ const [nodes, setNodes, onNodesChange] = useNodesState(initNodes);
+ const [edges, setEdges, onEdgesChange] = useEdgesState(initEdges);
+
+ const onConnect = useCallback((connection: Connection) => setEdges((eds) => addEdge(connection, eds)), [setEdges]);
+
+ return (
+
+
+
+
+ );
+};
+
+export default CustomNodeFlow;
diff --git a/packages/react/src/hooks/useHandleConnectionStatus.ts b/packages/react/src/hooks/useHandleConnections.ts
similarity index 86%
rename from packages/react/src/hooks/useHandleConnectionStatus.ts
rename to packages/react/src/hooks/useHandleConnections.ts
index 470cc077..f692ba37 100644
--- a/packages/react/src/hooks/useHandleConnectionStatus.ts
+++ b/packages/react/src/hooks/useHandleConnections.ts
@@ -4,7 +4,7 @@ import { Connection, HandleType } from '@xyflow/system';
import { useStore } from './useStore';
import { useNodeId } from '../contexts/NodeIdContext';
-type useHandleConnectionStatusParams = {
+type useHandleConnectionsParams = {
handleType: HandleType;
nodeId?: string;
handleId?: string | null;
@@ -12,6 +12,50 @@ type useHandleConnectionStatusParams = {
onDisconnect?: (connections: Connection[]) => void;
};
+/**
+ * Hook to check if a is connected to another and get the connections.
+ *
+ * @public
+ * @param param.handleType - 'source' or 'target'
+ * @param param.handleId - the handle id (this is only needed if the node has multiple handles of the same type)
+ * @param param.nodeId - node id - if not provided, the node id from the NodeIdContext is used
+ * @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 useHandleConnections({
+ handleType,
+ handleId = null,
+ nodeId,
+ onConnect,
+ onDisconnect,
+}: useHandleConnectionsParams): Connection[] {
+ const _nodeId = useNodeId();
+ const prevConnections = useRef