Handles
Handles are the connection points on nodes in React Flow. Our built-in nodes include one source and one target handle, but you can customize your nodes with as many different handles as you need.
Creating a Node with Handles
To create a custom node with handles, you can use the <Handle />
component provided by React Flow. This component allows you to define source and target handles for your custom nodes. Here’s an example of how to implement a custom node with two handles:
import { Handle } from '@xyflow/react';
export function CustomNode() {
return (
<div className="custom-node">
<div>Custom Node Content</div>
<Handle type="source" position="top" />
<Handle type="target" position="bottom" />
</div>
);
}
Using Multiple Handles
If you want to use multiple source or target handles in your custom node, you need to specify each handle with a unique id
. This allows React Flow to differentiate between the handles when connecting edges.
<Handle type="target" position="top" />
<Handle type="source" position="right" id="a" />
<Handle type="source" position="bottom" id="b" />
To connect an edge to a specific handle of a node, use the properties sourceHandle
(for the edge’s starting point) and targetHandle
(for the edge’s ending point). By defining sourceHandle
or targetHandle
with the appropriate handle id
, you instruct React Flow to attach the edge to that specific handle, ensuring that connections are made where you intend.
const initialEdges = [
{ id: 'edge-1', source: 'node-1', sourceHandle: 'a', target: 'node-2' },
{ id: 'edge-2', source: 'node-1', sourceHandle: 'b', target: 'node-3' },
];
In this case, the source node is node-1
for both handles but the handle id
s are different. One comes from handle id a
and the other one from b
. Both edges also have different target nodes:
import { useCallback, useState } from 'react';
import {
ReactFlow,
addEdge,
applyEdgeChanges,
applyNodeChanges,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import TextUpdaterNode from './TextUpdaterNode';
const rfStyle = {
backgroundColor: '#B8CEFF',
};
const initialNodes = [
{
id: 'node-1',
type: 'textUpdater',
position: { x: 100, y: 0 },
data: { value: 123 },
},
{
id: 'node-2',
type: 'output',
targetPosition: 'top',
position: { x: 0, y: 200 },
data: { label: 'node 2' },
},
{
id: 'node-3',
type: 'output',
targetPosition: 'top',
position: { x: 200, y: 200 },
data: { label: 'node 3' },
},
];
const initialEdges = [
{ id: 'edge-1', source: 'node-1', target: 'node-2', sourceHandle: 'a' },
{ id: 'edge-2', source: 'node-1', target: 'node-3', sourceHandle: 'b' },
];
// we define the nodeTypes outside of the component to prevent re-renderings
// you could also use useMemo inside the component
const nodeTypes = { textUpdater: TextUpdaterNode };
function Flow() {
const [nodes, setNodes] = useState(initialNodes);
const [edges, setEdges] = useState(initialEdges);
return (
<ReactFlow
nodes={nodes}
edges={edges}
nodeTypes={nodeTypes}
fitView
style={rfStyle}
/>
);
}
export default Flow;
If you are programmatically changing the position or number of handles
in your custom node, you will need to use the
useUpdateNodeInternals
hook
to properly notify React Flow of changes.
Custom handles
You can create your own custom handles by wrapping the <Handle />
component.
This example shows a custom handle that only allows connections when the
connection source matches a given id.
import { Handle, Position } from '@xyflow/react';
export const TargetHandleWithValidation = ({ position, source }) => (
<Handle
type="target"
position={position}
isValidConnection={(connection) => connection.source === source}
onConnect={(params) => console.log('handle onConnect', params)}
style={{ background: '#fff' }}
/>
);
Dynamic handles
If you are programmatically changing the position or number of handles in your
custom node, you need to update the node internals with the
useUpdateNodeInternals
hook.
You can find an example of how to implement a custom node with multiple handles in the custom node guide or in the custom node example.
Custom handle styles
Since the handle is a div, you can use CSS to style it or pass a style prop to customize a Handle. You can see this in the Add Node On Edge Drop and Simple Floating Edges examples.
Styling handles when connecting
The handle receives the additional class names connecting
when the connection
line is above the handle and valid
if the connection is valid. You can find an
example which uses these classes here.
Hiding Handles
- If you need to hide a handle for some reason, you must use
visibility: hidden
oropacity: 0
instead ofdisplay: none
. This is important because React Flow needs to calculate the dimensions of the handle to work properly and usingdisplay: none
will report a width and height of0
!