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.

FeatureReactFlowProvideruseReactFlow
PurposeProvides flow contextAccesses the flow instance
TypeContext providerReact hook
Main roleMakes flow state availableReads and manipulates flow data
UsageWrap componentsUse inside provider context
Best forShared flow accessProgrammatic 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 ReactFlowProvider when required.
  • Keep custom controls separate from the main canvas component.
  • Use useNodes and useEdges when components need reactive subscriptions.
  • Use useReactFlow for imperative operations and instance methods.
  • Avoid unnecessary subscriptions to large node or edge collections.
  • Keep state ownership clear when using controlled flows.
  • Use useUpdateNodeInternals when dynamic handle changes require recalculation.
  • Keep multiple flow instances isolated within their respective provider contexts.
Reactflow ProvidersOpen in New TabuseReacflow HookOpen in New Tab