Create onConnect handler
The onConnect handler is called whenever a new connection is made between two nodes. We
can use the addEdge utility function to create a new
edge and update the edge Array.
const onConnect = useCallback(
(params) => setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)),
[],
);Pass it to ReactFlow
Now we can pass the onConnect handler to the <ReactFlow /> component:
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitView
>
<Background />
<Controls />
</ReactFlow>Connectable flow
Try to connect the two nodes by dragging from on handle to another one. The onConnect
handler will be triggered, and the new edge will be added to the flow. 🥳
Example: learn/make-it-interactive-2
App.jsx
import { useState, useCallback } from 'react';
import {
ReactFlow,
Controls,
Background,
applyNodeChanges,
applyEdgeChanges,
addEdge,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const initialNodes = [
{
id: 'n1',
data: { label: 'Node 1' },
position: { x: 0, y: 0 },
type: 'input',
},
{
id: 'n2',
data: { label: 'Node 2' },
position: { x: 100, y: 100 },
},
];
const initialEdges = [];
function Flow() {
const [nodes, setNodes] = useState(initialNodes);
const [edges, setEdges] = useState(initialEdges);
const onNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[],
);
const onEdgesChange = useCallback(
(changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
[],
);
const onConnect = useCallback(
(params) => setEdges((eds) => addEdge(params, eds)),
[],
);
return (
<div style={{ height: '100%' }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitView
colorMode="system"
>
<Background />
<Controls />
</ReactFlow>
</div>
);
}
export default Flow;index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Flow Example</title>
<style>
html,
body {
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="./index.jsx"></script>
</body>
</html>index.jsx
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.querySelector('#app');
const root = createRoot(container);
root.render(<App />);Full code example 🏁
Example: learn/make-it-interactive-2
App.jsx
import { useState, useCallback } from 'react';
import {
ReactFlow,
Controls,
Background,
applyNodeChanges,
applyEdgeChanges,
addEdge,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const initialNodes = [
{
id: 'n1',
data: { label: 'Node 1' },
position: { x: 0, y: 0 },
type: 'input',
},
{
id: 'n2',
data: { label: 'Node 2' },
position: { x: 100, y: 100 },
},
];
const initialEdges = [];
function Flow() {
const [nodes, setNodes] = useState(initialNodes);
const [edges, setEdges] = useState(initialEdges);
const onNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[],
);
const onEdgesChange = useCallback(
(changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
[],
);
const onConnect = useCallback(
(params) => setEdges((eds) => addEdge(params, eds)),
[],
);
return (
<div style={{ height: '100%' }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitView
colorMode="system"
>
<Background />
<Controls />
</ReactFlow>
</div>
);
}
export default Flow;index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React Flow Example</title>
<style>
html,
body {
margin: 0;
font-family: sans-serif;
}
#app {
width: 100vw;
height: 100vh;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="./index.jsx"></script>
</body>
</html>index.jsx
import { createRoot } from 'react-dom/client';
import App from './App';
const container = document.querySelector('#app');
const root = createRoot(container);
root.render(<App />);What is happening here? Whenever React Flow triggers a change (node init, node drag, edge
select, etc.), the onNodesChange handler gets called. We export an applyNodeChanges
handler so that you don’t need to handle the changes by yourself. The applyNodeChanges
handler returns an updated array of nodes that is your new nodes array. You now have an
interactive flow with the following capabilities:
- selectable nodes and edges
- draggable nodes
- connectable nodes by dragging from one node handle to another
- multi-selection area by pressing
shift— the defaultselectionKeyCode - multi-selection by pressing
cmd— the defaultmultiSelectionKeyCode - removing selected elements by pressing
backspace— the defaultdeleteKeyCode
If you want to jump straight into creating your own application, we recommend checking out the Customization section. Otherwise keep reading to learn more about React Flows capabilities.