Handles
Beginner · 2 min read · Updated Nov 6, 2026
React Flow Handles: Creating Custom Node Connections
Handles are connection points that allow nodes to communicate with each other in React Flow. They define where edges enter and leave nodes, making them essential for building interactive workflow editors, flowcharts, and visual programming applications.
With the <Handle /> component, developers can create multiple connection points, customize their positions, apply unique styles, and dynamically manage node connections.
1. Creating Handles in Custom Nodes
React Flow provides the <Handle /> component to add connection points to custom nodes. Use source handles for outgoing connections and target handles for incoming connections.
Code Example
import { Handle, Position } from '@xyflow/react';
export function CustomNode({ data }) {
return (
<div className="custom-node">
<Handle
type="target"
position={Position.Top}
/>
<strong>{data.label}</strong>
<Handle
type="source"
position={Position.Bottom}
/>
</div>
);
}
Key Features:
- Create incoming and outgoing connections.
- Position handles on different sides of nodes.
- Customize handle appearance and behavior.
- Support reusable custom node components.
2. Using Multiple Handles
React Flow supports multiple source and target handles within a single node. Assign a unique id to each handle so edges can connect to specific connection points.
Code Example
import { Handle, Position } from '@xyflow/react';
export function MultiHandleNode() {
return (
<div className="custom-node">
<Handle
type="target"
position={Position.Left}
id="input-1"
/>
<strong>Multi Output Node</strong>
<Handle
type="source"
position={Position.Right}
id="output-1"
style={{ top: '30%' }}
/>
<Handle
type="source"
position={Position.Right}
id="output-2"
style={{ top: '70%' }}
/>
</div>
);
}
To connect an edge to a specific handle, use sourceHandle and targetHandle.
const edges = [
{
id: 'e1',
source: '1',
sourceHandle: 'output-1',
target: '2',
},
{
id: 'e2',
source: '1',
sourceHandle: 'output-2',
target: '3',
},
];
Multiple handles are especially useful for AI workflow builders, automation systems, and conditional branching diagrams.
3. Creating Custom Handles
You can customize the appearance of handles by wrapping icons or other React components inside the <Handle /> component. This allows you to create visually distinctive connection points.
Code Example
import { Handle, Position } from '@xyflow/react';
export function CustomIconHandle() {
return (
<div className="custom-node">
<Handle
type="source"
position={Position.Right}
style={{
width: 24,
height: 24,
background: 'none',
border: 'none',
}}
>
<span className="handle-icon">➜</span>
</Handle>
<strong>Custom Handle</strong>
</div>
);
}
.handle-icon {
position: absolute;
left: 0;
top: 0;
font-size: 20px;
pointer-events: none;
}
Custom handles help create modern node interfaces with icons, buttons, and branded connection points.
4. Using Typeless Handles
React Flow supports flexible connections using typeless handles. By setting connectionMode to ConnectionMode.Loose, a handle can be used for both incoming and outgoing connections without specifying its type.
Code Example
import {
ReactFlow,
Handle,
Position,
ConnectionMode,
} from '@xyflow/react';
function FlexibleNode() {
return (
<div className="custom-node">
<Handle position={Position.Left} />
<strong>Flexible Node</strong>
<Handle position={Position.Right} />
</div>
);
}
<ReactFlow
nodes={nodes}
edges={edges}
connectionMode={ConnectionMode.Loose}
/>;
This approach is useful for flexible diagram editors where connections can start or end at any handle.
5. Dynamically Updating Handles
Sometimes the number or position of handles changes based on node data or user interactions. React Flow provides the useUpdateNodeInternals() Hook to recalculate handle positions and node dimensions.
Code Example
import { useEffect } from 'react';
import {
Handle,
Position,
useUpdateNodeInternals,
useNodeId,
} from '@xyflow/react';
export function DynamicNode({ data }) {
const nodeId = useNodeId();
const updateNodeInternals = useUpdateNodeInternals();
useEffect(() => {
updateNodeInternals(nodeId);
}, [data.outputs, nodeId, updateNodeInternals]);
return (
<div className="custom-node">
<strong>Dynamic Node</strong>
{data.outputs.map((output, index) => (
<Handle
key={output.id}
id={output.id}
type="source"
position={Position.Right}
style={{
top: `${((index + 1) /
(data.outputs.length + 1)) * 100}%`,
}}
/>
))}
</div>
);
}
This technique is useful for dynamic workflow builders where users can add, remove, or reposition connection points.
6. Customizing Handle Styles
Handles can be styled using inline CSS or external stylesheets. You can customize their size, color, border, shape, and position to match your application's design.
Code Example
<Handle
type="source"
position={Position.Right}
style={{
width: 12,
height: 12,
background: '#6366f1',
border: '2px solid white',
borderRadius: '50%',
}}
/>
You can also use CSS classes to style handles consistently across your application.
.react-flow__handle {
width: 12px;
height: 12px;
background: #6366f1;
border: 2px solid white;
}
.react-flow__handle:hover {
background: #4f46e5;
transform: scale(1.2);
}
7. Styling Handles During Connections
React Flow automatically adds CSS classes to handles during connection interactions. The connecting class indicates an active connection attempt, while valid indicates a valid connection target.
Code Example
.react-flow__handle.connecting {
background: #f59e0b;
}
.react-flow__handle.valid {
background: #22c55e;
box-shadow: 0 0 8px rgba(34, 197, 94, 0.5);
}
These visual states provide useful feedback and make connecting nodes more intuitive.
8. Hiding Handles in React Flow
You can hide handles without removing their dimensions from the DOM. Use visibility: hidden or opacity: 0 instead of display: none, because React Flow needs handle dimensions to calculate connections correctly.
Code Example
<Handle
type="source"
position={Position.Right}
style={{
visibility: 'hidden',
}}
/>
Alternatively, use opacity to make a handle invisible while preserving its layout and connection functionality.
.hidden-handle {
opacity: 0;
}