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 { Position, Handle } from '@xyflow/react';
export function CustomNode() {
return (
<div className="custom-node">
<div>Custom Node Content</div>
<Handle type="source" position={Position.Top} />
<Handle type="target" position={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={Position.Top} />
<Handle type="source" position={Position.Right} id="a" />
<Handle type="source" position={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: 'n1-n2', source: 'n1', sourceHandle: 'a', target: 'n2' },
{ id: 'n1-n3', source: 'n1', sourceHandle: 'b', target: 'n3' },
];In this case, the source node is n1 for both handles but the handle ids are different.
One comes from handle id a and the other one from b. Both edges also have different
target nodes:
By default React Flow positions a handle in the center of the specified side. If you want to display multiple handles on a side, you can adjust the position via inline styles or overwrite the default CSS and position it on your own.
Custom handles
You can use any custom component as a Handle by wrapping it with the
<Handle /> component. Follow these steps to
integrate your custom component:
- Wrap your custom component with
<Handle />component. - Hide the built-in
<Handle />appearance by settingborderandbackgroundtonone. - Set the
widthandheightof<Handle />to match your custom component. - Style the child component with
pointer-events: none. - Then, reposition the child custom component using CSS position properties like
top, leftif necessary to position it perfectly inside the<Handle />component.
This example shows a Material UI icon ArrowCircleRightIcon used as a Handle.
import { Handle, Position } from '@xyflow/react';
import ArrowCircleRightIcon from '@mui/icons-material/ArrowCircleRight';
export function CustomNode() {
return (
<div className="react-flow__node-default">
<Handle
position={Position.Right}
type="source"
style={{
background: 'none',
border: 'none',
width: '1em',
height: '1em',
}}
>
<ArrowCircleRightIcon
style={{
pointerEvents: 'none',
fontSize: '1em',
left: 0,
position: 'absolute',
}}
/>
</Handle>
Custom Node
</div>
);
}Typeless handles
If you want to create a handle that does not have a specific type (source or target), you
can set connectionMode to Loose in the
<ReactFlow /> component. This allows the handle to be used for both incoming and
outgoing connections.
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.
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 or
opacity: 0 instead of display: none. This is important because React Flow needs to
calculate the dimensions of the handle to work properly and using display: none will
report a width and height of 0!