Hooks and Providers
Advanced · 5 min read · Updated Nov 8, 2026
Hooks and Providers: Manage Flow State and Build Custom Components
React Flow provides a powerful collection of hooks and context providers that make it easier to manage nodes, edges, viewport settings, and other flow-related functionality. These tools help developers build interactive workflow editors, visual programming interfaces, and advanced node-based applications.
When developing a complex React Flow application, you may need to access the flow state from components outside the main canvas, update nodes programmatically, or create custom controls that interact with the diagram.
This is where React Flow Hooks and Providers become essential.
In this guide, you'll learn how to use ReactFlowProvider, access flow methods with useReactFlow, and work with other useful hooks to build more flexible React Flow applications.
What Are React Flow Hooks?
React Flow hooks are reusable functions that allow components to interact with the flow's internal state and functionality.
Instead of passing nodes, edges, and viewport information through multiple component levels, you can use dedicated hooks to access the information you need.
React Flow provides hooks for:
- Reading and updating nodes and edges.
- Accessing the React Flow instance.
- Managing viewport interactions.
- Detecting node connections.
- Tracking selection changes.
- Updating node internals.
- Accessing node-specific information.
These hooks help keep your application modular and make it easier to build reusable components.
What Is ReactFlowProvider?
ReactFlowProvider is a context provider that makes React Flow's internal state accessible throughout a component tree.
Many React Flow hooks depend on this provider to access the flow instance and its data. It is especially useful when components need to interact with the canvas but are not direct children of the <ReactFlow /> component.
You may need ReactFlowProvider when:
- A toolbar outside the canvas needs to control the flow.
- You want to access nodes and edges from external components.
- Your application contains multiple React Flow instances.
- You are using client-side routing.
- Shared components need access to flow methods.
How to Use ReactFlowProvider
Wrap your React Flow application with ReactFlowProvider to make the context available to its child components.
import {
ReactFlow,
ReactFlowProvider,
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
function FlowEditor() {
return (
<div style={{ width: '100%', height: 500 }}>
<ReactFlow
nodes={[]}
edges={[]}
fitView
/>
</div>
);
}
export default function App() {
return (
<ReactFlowProvider>
<FlowEditor />
</ReactFlowProvider>
);
}
The provider should be placed above the components that use React Flow hooks. This allows those components to access the same flow context.
Understanding the useReactFlow Hook
The useReactFlow hook provides access to the ReactFlowInstance, allowing you to interact with the flow programmatically.
You can use it to:
- Get the current nodes and edges.
- Add, update, or remove nodes.
- Add, update, or remove edges.
- Control zoom and viewport positioning.
- Fit the diagram into the available canvas.
This is especially useful when building custom toolbars, workflow controls, and interactive editor features.
Example: Accessing React Flow Methods
import { useReactFlow } from '@xyflow/react';
function FlowToolbar() {
const {
getNodes,
getEdges,
fitView,
zoomIn,
zoomOut,
} = useReactFlow();
const handleLogFlow = () => {
console.log('Nodes:', getNodes());
console.log('Edges:', getEdges());
};
return (
<div>
<button onClick={handleLogFlow}>
Log Flow Data
</button>
<button onClick={() => fitView()}>
Fit View
</button>
<button onClick={() => zoomIn()}>
Zoom In
</button>
<button onClick={() => zoomOut()}>
Zoom Out
</button>
</div>
);
}
Render FlowToolbar inside the React Flow context, such as within the ReactFlowProvider wrapper shown earlier.
Important: getNodes() and getEdges() return the current flow data when called. They do not subscribe the component to state changes. If your component needs to re-render whenever nodes or edges change, use useNodes() or useEdges() instead.
Useful React Flow Hooks for State Management
React Flow includes several hooks for accessing different parts of the diagram. Choosing the right hook helps avoid unnecessary state management and keeps components focused.
1. useNodes
The useNodes hook provides access to the current nodes in the flow and subscribes the component to node changes.
import { useNodes } from '@xyflow/react';
function NodeCounter() {
const nodes = useNodes();
return (
<div>
Total Nodes: {nodes.length}
</div>
);
}
Use this hook when you need to display node information or build components that respond to node updates.
2. useEdges
The useEdges hook provides access to the current edges and subscribes the component to edge changes.
import { useEdges } from '@xyflow/react';
function EdgeCounter() {
const edges = useEdges();
return (
<div>
Total Connections: {edges.length}
</div>
);
}
This is useful for displaying connection counts, monitoring relationships, and creating workflow statistics.
3. useNodesState
The useNodesState hook provides a convenient way to manage nodes in a controlled React Flow application.
import { useNodesState } from '@xyflow/react';
const [nodes, setNodes, onNodesChange] =
useNodesState([
{
id: '1',
position: { x: 100, y: 100 },
data: { label: 'Start' },
},
]);
It returns three values:
nodes: The current node array.setNodes: A function for updating nodes.onNodesChange: A handler for applying node changes.
4. useEdgesState
Similarly, useEdgesState helps manage edges in a controlled React Flow application.
import { useEdgesState } from '@xyflow/react';
const [edges, setEdges, onEdgesChange] =
useEdgesState([
{
id: 'e1-2',
source: '1',
target: '2',
},
]);
It is particularly useful when building applications where users can create, remove, or modify connections interactively.
5. useViewport
The useViewport hook provides the current viewport information, including the horizontal position, vertical position, and zoom level.
import { useViewport } from '@xyflow/react';
function ViewportInfo() {
const { x, y, zoom } = useViewport();
return (
<div>
<p>X: {x}</p>
<p>Y: {y}</p>
<p>Zoom: {zoom.toFixed(2)}</p>
</div>
);
}
You can use it to build custom zoom indicators, viewport displays, and canvas-related controls.
6. useUpdateNodeInternals
The useUpdateNodeInternals hook allows you to tell React Flow to recalculate a node's internal dimensions and handle positions.
This is useful when a custom node dynamically adds, removes, or changes handles.
import { useUpdateNodeInternals } from '@xyflow/react';
function UpdateHandlesButton({ nodeId }: { nodeId: string }) {
const updateNodeInternals = useUpdateNodeInternals();
return (
<button
onClick={() => updateNodeInternals(nodeId)}
>
Update Node Handles
</button>
);
}
Use this hook when dynamic changes affect a node's handle layout.
Building Custom Components with React Flow Hooks
One of the biggest advantages of React Flow hooks is the ability to create reusable components that interact with the canvas without placing all application logic inside the main editor.
For example, you can create:
- Custom toolbars for zoom and viewport controls.
- Node counters and edge counters.
- Workflow validation panels.
- Dynamic node management controls.
- Selection-based action menus.
- Custom flow analytics panels.
These components can be developed independently while still accessing the flow context through React Flow hooks.
ReactFlowProvider vs useReactFlow
ReactFlowProvider and useReactFlow serve different purposes, but they work together.
| Feature | ReactFlowProvider | useReactFlow |
|---|---|---|
| Purpose | Provides flow context | Accesses the flow instance |
| Type | Context provider | React hook |
| Main role | Makes flow state available | Reads and manipulates flow data |
| Usage | Wrap components | Use inside provider context |
| Best for | Shared flow access | Programmatic flow control |
In simple terms, ReactFlowProvider makes the context available, while useReactFlow allows components to interact with it.
Best Practices for Using React Flow Hooks
Follow these practices when building advanced React Flow applications:
- Wrap hook-dependent components with
ReactFlowProviderwhen required. - Keep custom controls separate from the main canvas component.
- Use
useNodesanduseEdgeswhen components need reactive subscriptions. - Use
useReactFlowfor imperative operations and instance methods. - Avoid unnecessary subscriptions to large node or edge collections.
- Keep state ownership clear when using controlled flows.
- Use
useUpdateNodeInternalswhen dynamic handle changes require recalculation. - Keep multiple flow instances isolated within their respective provider contexts.