# ==================================
# API Reference
# ==================================
# ======= The Background component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/Background/Background.tsx)
The `` component makes it convenient to render different types of
backgrounds common in node-based UIs. It comes with three variants: `lines`,
`dots` and `cross`.
```jsx
import { useState } from 'react';
import { ReactFlow, Background, BackgroundVariant } from '@xyflow/react';
export default function Flow() {
return (
);
}
```
## Props
## Examples
### Combining multiple backgrounds
It is possible to layer multiple `` components on top of one another
to create something more interesting. The following example shows how to render a
square grid accented every 10th line.
```tsx
import { ReactFlow, Background, BackgroundVariant } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
export default function Flow() {
return (
);
}
```
## Notes
* When combining multiple `` components it's important to give each
of them a unique `id` prop!
# ======= The BaseEdge component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/Edges/BaseEdge.tsx)
The `` component gets used internally for all the edges. It can be
used inside a custom edge and handles the invisible helper edge and the edge label
for you.
```jsx
import { BaseEdge } from '@xyflow/react';
export function CustomEdge({ sourceX, sourceY, targetX, targetY, ...props }) {
const [edgePath] = getStraightPath({
sourceX,
sourceY,
targetX,
targetY,
});
const { label, labelStyle, markerStart, markerEnd, interactionWidth } = props;
return (
);
}
```
## Props
## Notes
* If you want to use an edge marker with the [``](/api-reference/components/base-edge) component,
you can pass the `markerStart` or `markerEnd` props passed to your custom edge
through to the [``](/api-reference/components/base-edge) component. You can see all the props
passed to a custom edge by looking at the [`EdgeProps`](/api-reference/types/edge-props) type.
# ======= The ControlButton component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/ControlButton.tsx)
You can add buttons to the control panel by using the `` component
and pass it as a child to the [``](/api-reference/components/controls) component.
```jsx
import { MagicWand } from '@radix-ui/react-icons'
import { ReactFlow, Controls, ControlButton } from '@xyflow/react'
export default function Flow() {
return (
alert('Something magical just happened. ✨')}>
)
}
```
## Props
The `` component accepts any prop valid on a HTML ``
element.
# ======= The Controls component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/Controls/Controls.tsx)
The `` component renders a small panel that contains convenient
buttons to zoom in, zoom out, fit the view, and lock the viewport.
```tsx
import { ReactFlow, Controls } from '@xyflow/react'
export default function Flow() {
return (
)
}
```
## Props
For TypeScript users, the props type for the `` component is exported
as `ControlProps`.
## Notes
* To extend or customize the controls, you can use the [``](/api-reference/components/control-button)
component
# ======= The EdgeLabelRenderer component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/EdgeLabelRenderer/index.tsx)
Edges are SVG-based. If you want to render more complex labels you can use the
`` component to access a div based renderer. This component
is a portal that renders the label in a `
` that is positioned on top of
the edges. You can see an example usage of the component in the [edge label renderer](/examples/edges/edge-label-renderer)
example.
```jsx
import React from 'react';
import { getBezierPath, EdgeLabelRenderer, BaseEdge } from '@xyflow/react';
const CustomEdge = ({ id, data, ...props }) => {
const [edgePath, labelX, labelY] = getBezierPath(props);
return (
<>
{data.label}
>
);
};
export default CustomEdge;
```
## Props
## Notes
* The `` has no pointer events by default. If you want to
add mouse interactions you need to set the style `pointerEvents: 'all'` and add
the `nopan` class on the label or the element you want to interact with.
# ======= The EdgeText component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/Edges/EdgeText.tsx)
You can use the `` component as a helper component to display text
within your custom edges.
```jsx
import { EdgeText } from '@xyflow/react';
export function CustomEdgeLabel({ label }) {
return (
);
}
```
## Props
For TypeScript users, the props type for the `` component is exported
as `EdgeTextProps`.
Additionally, you may also pass any standard React HTML attributes such as `onClick`,
`className` and so on.
# ======= The Handle component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/Handle/index.tsx)
The `` component is used in your [custom nodes](/learn/customization/custom-nodes)
to define connection points.
```jsx
import { Handle, Position } from '@xyflow/react';
export const CustomNode = ({ data }) => {
return (
<>
{data.label}
>
);
};
```
## Props
For TypeScript users, the props type for the `` component is exported
as `HandleProps`.
import { ApiReferenceSummary } from 'xy-shared/server';
# Components
# ======= The MiniMap component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/MiniMap/MiniMap.tsx)
The `` component can be used to render an overview of your flow. It
renders each node as an SVG element and visualizes where the current viewport is
in relation to the rest of the flow.
```jsx
import { ReactFlow, MiniMap } from '@xyflow/react';
export default function Flow() {
return (
);
}
```
## Props
For TypeScript users, the props type for the `` component is exported
as `MiniMapProps`.
## Examples
### Making the mini map interactive
By default, the mini map is non-interactive. To allow users to interact with the
viewport by panning or zooming the minimap, you can set either of the `zoomable`
or `pannable` (or both!) props to `true`.
```jsx
import { ReactFlow, MiniMap } from '@xyflow/react';
export default function Flow() {
return (
);
}
```
### Implement a custom mini map node
It is possible to pass a custom component to the `nodeComponent` prop to change
how nodes are rendered in the mini map. If you do this you **must** use only
SVG elements in your component if you want it to work correctly.
```jsx
import { ReactFlow, MiniMap } from '@xyflow/react';
export default function Flow() {
return (
);
}
function MiniMapNode({ x, y }) {
return ;
}
```
Check out the documentation for [`MiniMapNodeProps`](/api-reference/types/mini-map-node-props)
to see what props are passed to your custom component.
### Customising mini map node color
The `nodeColor`, `nodeStrokeColor`, and `nodeClassName` props can be a function
that takes a [`Node`](/api-reference/types/node) and computes a value for the prop. This can
be used to customize the appearance of each mini map node.
This example shows how to color each mini map node based on the node's type:
```jsx
import { ReactFlow, MiniMap } from '@xyflow/react';
export default function Flow() {
return (
);
}
function nodeColor(node) {
switch (node.type) {
case 'input':
return '#6ede87';
case 'output':
return '#6865A5';
default:
return '#ff0072';
}
}
```
## TypeScript
This component accepts a generic type argument of custom node types. See this
[section in our Typescript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
nodeColor={nodeColor} />
```
# ======= The NodeResizeControl component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx)
To create your own resizing UI, you can use the `NodeResizeControl` component where you can pass children (such as icons).
## Props
For TypeScript users, the props type for the `` component is exported
as `ResizeControlProps`.
# ======= The NodeResizer component =======
import { RemoteCodeViewer } from 'xy-shared/server';
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/NodeResizer/NodeResizer.tsx)
The `` component can be used to add a resize functionality to your
nodes. It renders draggable controls around the node to resize in all directions.
```jsx
import { memo } from 'react';
import { Handle, Position, NodeResizer } from '@xyflow/react';
const ResizableNode = ({ data }) => {
return (
<>
{data.label}
>
);
};
export default memo(ResizableNode);
```
## Props
For TypeScript users, the props type for the `` component is exported
as `NodeResizerProps`.
## Examples
Head over to the [example page](/examples/nodes/node-resizer) to see how this is done.
### Custom Resize Controls
To build custom resize controls, you can use the [NodeResizeControl](/api-reference/components/node-resize-control) component and customize it.
## Notes
* Take a look at the docs for the [`NodeProps`](/api-reference/types/node-props) type or the
guide on [custom nodes](/learn/customization/custom-nodes) to see how to
implement your own nodes.
# ======= The NodeToolbar component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx)
This component can render a toolbar or tooltip to one side of a custom node. This
toolbar doesn't scale with the viewport so that the content is always visible.
```jsx
import { memo } from 'react';
import { Handle, Position, NodeToolbar } from '@xyflow/react';
const CustomNode = ({ data }) => {
return (
<>
{data.label}
>
);
};
export default memo(CustomNode);
```
## Props
For TypeScript users, the props type for the `` component is exported
as `NodeToolbarProps`. Additionally, the `` component accepts all props of the HTML ``
element.
## Notes
* By default, the toolbar is only visible when a node is selected. If multiple
nodes are selected it will not be visible to prevent overlapping toolbars or
clutter. You can override this behavior by setting the `isVisible` prop to
`true`.
# ======= The Panel component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/Panel/index.tsx)
The `` component helps you position content above the viewport. It is
used internally by the [``](/api-reference/components/minimap) and [``](/api-reference/components/controls)
components.
```jsx
import { ReactFlow, Panel } from '@xyflow/react';
export default function Flow() {
return (
top-lefttop-centertop-rightbottom-leftbottom-centerbottom-rightcenter-leftcenter-right
);
}
```
## Props
For TypeScript users, the props type for the `` component is exported
as `PanelProps`. Additionally, the `` component accepts all props of the HTML ``
element.
# ======= The ViewportPortal component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/ViewportPortal/index.tsx)
`` component can be used to add components to the same viewport of the flow where nodes and edges are rendered.
This is useful when you want to render your own components that adhere to the same coordinate system as the nodes & edges and are also
affected by zooming and panning
```jsx
import React from 'react';
import { ViewportPortal } from '@xyflow/react';
export default function () {
return (
This div is positioned at [100, 100] on the flow.
);
}
```
## Props
import { ApiReferenceSummary } from 'xy-shared/server';
# Hooks
# useConnection()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useConnection.ts)
The `useConnection` hook returns the current connection state when there is an active connection interaction. If no connection interaction is active, it returns `null` for every property. A typical use case for this hook is to colorize handles based on a certain condition (e.g. if the connection is valid or not).
```tsx
import { useConnection } from '@xyflow/react';
export default function App() {
const connection = useConnection();
return (
{connection ? `Someone is trying to make a connection from ${connection.fromNode} to this one.` : 'There are currently no incoming connections!'}
);
}
```
## Signature
# useEdgesState()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useNodesEdgesState.ts)
This hook makes it easy to prototype a controlled flow where you manage the
state of nodes and edges outside the `ReactFlowInstance`. You can think of it
like React's `useState` hook with an additional helper callback.
```jsx
import { ReactFlow, useNodesState, useEdgesState } from '@xyflow/react';
const initialNodes = [];
const initialEdges = [];
export default function () {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
return (
);
}
```
## Signature
## TypeScript
This hook accepts a generic type argument of custom edge types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const nodes = useEdgesState();
```
## Notes
* This hook was created to make prototyping easier and our documentation
examples clearer. Although it is OK to use this hook in production, in
practice you may want to use a more sophisticated state management solution
like [Zustand](/docs/guides/state-management/) instead.
# useEdges()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useEdges.ts)
This hook returns an array of the current edges. Components that use this hook
will re-render **whenever any edge changes**.
```jsx
import { useEdges } from '@xyflow/react';
export default function () {
const edges = useEdges();
return
There are currently {edges.length} edges!
;
}
```
## Signature
## TypeScript
This hook accepts a generic type argument of custom edge types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const nodes = useEdges();
```
## Notes
* Relying on `useEdges` unnecessarily can be a common cause of performance
issues. Whenever any edge changes, this hook will cause the component to
re-render. Often we actually care about something more specific, like when
the *number* of edges changes: where possible try to use
[`useStore`](/api-reference/hooks/use-store) instead.
# useHandleConnections()
> \[!WARNING]
>
> `useHandleConnections` is deprecated in favor of the more capable
> [useNodeConnections](/api-reference/hooks/use-node-connections).
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useHandleConnections.ts)
This hook returns an array connections on a specific handle or handle type.
```jsx
import { useHandleConnections } from '@xyflow/react';
export default function () {
const connections = useHandleConnections({ type: 'target', id: 'my-handle' });
return (
There are currently {connections.length} incoming connections!
);
}
```
## Signature
# useInternalNode()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useInternalNode.ts)
This hook returns the internal representation of a specific node. Components that use this hook
will re-render **whenever any node changes**, including when a node is selected
or moved.
```jsx
import { useInternalNode } from '@xyflow/react';
export default function () {
const internalNode = useInternalNode('node-1');
const absolutePosition = internalNode.internals.positionAbsolute;
return (
The absolute position of the node is at:
x: {absolutePosition.x}
y: {absolutePosition.y}
);
}
```
## Signature
## TypeScript
This hook accepts a generic type argument of custom node types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const internalNode = useInternalNode();
```
# useKeyPress()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useKeyPress.ts)
This hook lets you listen for specific key codes and tells you whether they are
currently pressed or not.
```jsx
import { useKeyPress } from '@xyflow/react';
export default function () {
const spacePressed = useKeyPress('Space');
const cmdAndSPressed = useKeyPress(['Meta+s', 'Strg+s']);
return (
{spacePressed &&
Space pressed!
}
{cmdAndSPressed &&
Cmd + S pressed!
}
);
}
```
## Signature
## Notes
* This hook does not rely on a `ReactFlowInstance` so you are free to use it
anywhere in your app!
# useNodeConnections()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useNodeConnections.ts)
This hook returns an array of connections on a specific node, handle type ('source', 'target') or handle ID.
```jsx
import { useNodeConnections } from '@xyflow/react';
export default function () {
const connections = useNodeConnections({
handleType: 'target',
handleId: 'my-handle',
});
return (
There are currently {connections.length} incoming connections!
);
}
```
## Signature
# useNodeId()
[Source on Github](https://github.com/xyflow/xyflow/blob/v11/packages/core/src/contexts/NodeIdContext.ts/#L7)
You can use this hook to get the id of the node it is used inside. It is useful
if you need the node's id deeper in the render tree but don't want to manually
drill down the id as a prop.
```js
import { useNodeId } from '@xyflow/react';
export default function CustomNode() {
return (
This node has an id of
);
}
function NodeIdDisplay() {
const nodeId = useNodeId();
return {nodeId};
}
```
## Signature
## Notes
* This hook should only be used within a custom node or its children.
# useNodesData()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useNodesData.ts)
This hook lets you subscribe to changes of a specific nodes `data` object.
```jsx
import { useNodesData } from '@xyflow/react';
export default function () {
const nodeData = useNodesData('nodeId-1');
const nodesData = useNodesData(['nodeId-1', 'nodeId-2']);
}
```
## Signature
## TypeScript
This hook accepts a generic type argument of custom node types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const nodesData = useNodesData(['nodeId-1', 'nodeId-2']);
```
# useNodesInitialized()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useNodesInitialized.ts)
This hook tells you whether all the nodes in a flow have been measured and given
a width and height. When you add a node to the flow, this hook will return
`false` and then `true` again once the node has been measured.
```jsx
import { useReactFlow, useNodesInitialized } from '@xyflow/react';
import { useEffect, useState } from 'react';
const options = {
includeHiddenNodes: false,
};
export default function useLayout() {
const { getNodes } = useReactFlow();
const nodesInitialized = useNodesInitialized(options);
const [layoutedNodes, setLayoutedNodes] = useState(getNodes());
useEffect(() => {
if (nodesInitialized) {
setLayoutedNodes(yourLayoutingFunction(getNodes()));
}
}, [nodesInitialized]);
return layoutedNodes;
}
```
## Signature
## Notes
* This hook always returns `false` if the internal nodes array is empty.
# useNodesState()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useNodesEdgesState.ts)
This hook makes it easy to prototype a controlled flow where you manage the
state of nodes and edges outside the `ReactFlowInstance`. You can think of it
like React's `useState` hook with an additional helper callback.
```jsx
import { ReactFlow, useNodesState, useEdgesState } from '@xyflow/react';
const initialNodes = [];
const initialEdges = [];
export default function () {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
return (
);
}
```
## Signature
## TypeScript
This hook accepts a generic type argument of custom node types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const nodes = useNodesState();
```
## Notes
* This hook was created to make prototyping easier and our documentation
examples clearer. Although it is OK to use this hook in production, in
practice you may want to use a more sophisticated state management solution
like [Zustand](/docs/guides/state-management/) instead.
# useNodes()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useNodes.ts)
This hook returns an array of the current nodes. Components that use this hook
will re-render **whenever any node changes**, including when a node is selected
or moved.
```jsx
import { useNodes } from '@xyflow/react';
export default function () {
const nodes = useNodes();
return
There are currently {nodes.length} nodes!
;
}
```
## Signature
## TypeScript
This hook accepts a generic type argument of custom node types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const nodes = useNodes();
```
## Notes
* Relying on `useNodes` unnecessarily can be a common cause of performance
issues. Whenever any node changes, this hook will cause the component to
re-render. Often we actually care about something more specific, like when
the *number* of nodes changes: where possible try to use
[`useStore`](/api-reference/hooks/use-store) instead.
# useOnSelectionChange()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useOnSelectionChange.ts)
This hook lets you listen for changes to both node and edge selection. As the
name implies, the callback you provide will be called whenever the selection of
*either* nodes or edges changes.
> \[!WARNING]
>
> You need to memoize the passed `onChange` handler, otherwise the hook will not
> work correctly.
```jsx
import { useState } from 'react';
import { ReactFlow, useOnSelectionChange } from '@xyflow/react';
function SelectionDisplay() {
const [selectedNodes, setSelectedNodes] = useState([]);
const [selectedEdges, setSelectedEdges] = useState([]);
// the passed handler has to be memoized, otherwise the hook will not work correctly
const onChange = useCallback(({ nodes, edges }) => {
setSelectedNodes(nodes.map((node) => node.id));
setSelectedEdges(edges.map((edge) => edge.id));
}, []);
useOnSelectionChange({
onChange,
});
return (
Selected nodes: {selectedNodes.join(', ')}
Selected edges: {selectedEdges.join(', ')}
);
}
```
## Signature
## Notes
* This hook can only be used in a component that is a child of a
[``](/api-reference/react-flow-provider) or a
[``](/api-reference/react-flow) component.
# useOnViewportChange()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useOnViewportChange.ts)
The `useOnViewportChange` hook lets you listen for changes to the viewport such
as panning and zooming. You can provide a callback for each phase of a viewport
change: `onStart`, `onChange`, and `onEnd`.
```tsx
import { useCallback } from 'react';
import { useOnViewportChange } from '@xyflow/react';
function ViewportChangeLogger() {
useOnViewportChange({
onStart: (viewport: Viewport) => console.log('start', viewport),
onChange: (viewport: Viewport) => console.log('change', viewport),
onEnd: (viewport: Viewport) => console.log('end', viewport),
});
return null;
}
```
## Signature
## Notes
* This hook can only be used in a component that is a child of a
[``](/api-reference/react-flow-provider) or a
[``](/api-reference/react-flow) component.
# useReactFlow()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useReactFlow.ts)
This hook returns a [`ReactFlowInstance`](/api-reference/types/react-flow-instance) that can
be used to update nodes and edges, manipulate the viewport, or query the current
state of the flow.
```jsx
import { useCallback, useState } from 'react';
import { useReactFlow } from '@xyflow/react';
export function NodeCounter() {
const reactFlow = useReactFlow();
const [count, setCount] = useState(0);
const countNodes = useCallback(() => {
setCount(reactFlow.getNodes().length);
// you need to pass it as a dependency if you are using it with useEffect or useCallback
// because at the first render, it's not initialized yet and some functions might not work.
}, [reactFlow]);
return (
There are {count} nodes in the flow.
);
}
```
## Signature
## TypeScript
This hook accepts a generic type argument of custom node & edge types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const reactFlow = useReactFlow();
```
## Notes
* This hook can only be used in a component that is a child of a
[``](/api-reference/react-flow-provider) or a
[``](/api-reference/react-flow) component.
* Unlike [`useNodes`](/api-reference/hooks/use-nodes) or [`useEdges`](/api-reference/hooks/use-edges), this hook won't
cause your component to re-render when state changes. Instead, you can query
the state when you need it by using methods on the [`ReactFlowInstance`](/api-reference/types/react-flow-instance)
this hook returns.
# useStoreApi()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useStore.ts)
In some cases, you might need to access the store directly. This hook returns the store object which can be used on demand to access the state or dispatch actions.
> \[!NOTE]
>
> This hook should only be used if there is no other way to access the internal
> state. For many of the common use cases, there are dedicated hooks available
> such as [`useReactFlow`](/api-reference/hooks/use-react-flow),
> [`useViewport`](/api-reference/hooks/use-viewport), etc.
```tsx
import { useState, useCallback } from 'react';
import { ReactFlow, useStoreApi } from '@xyflow/react';
const NodesLengthDisplay = () => {
const [nodesLength, setNodesLength] = useState(0);
const store = useStoreApi();
const onClick = useCallback(() => {
const { nodes } = store.getState();
const length = nodes.length || 0;
setNodesLength(length);
}, [store]);
return (
The current number of nodes is: {nodesLength}
);
};
function Flow() {
return (
);
}
```
This example computes the number of nodes in the flow *on-demand*. This is in
contrast to the example in the [`useStore`](/api-reference/hooks/use-store) hook that re-renders
the component whenever the number of nodes changes.
Choosing whether to calculate values on-demand or to subscribe to changes as they
happen is a bit of a balancing act. On the one hand, putting too many heavy
calculations in an event handler can make your app feel sluggish or unresponsive.
On the other hand, computing values eagerly can lead to slow or unnecessary
re-renders.
We make both this hook and [`useStore`](/api-reference/hooks/use-store) available so that you can
choose the approach that works best for your use-case.
## Signature
## TypeScript
This hook accepts a generic type argument of custom node & edge types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const store = useStoreApi();
```
import { Callout } from 'nextra/components';
# useStore()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useStore.ts)
This hook can be used to subscribe to internal state changes of the React Flow
component. The `useStore` hook is re-exported from the [Zustand](https://github.com/pmndrs/zustand)
state management library, so you should check out their docs for more details.
This hook should only be used if there is no other way to access the internal
state. For many of the common use cases, there are dedicated hooks available
such as [`useReactFlow`](/api-reference/hooks/use-react-flow),
[`useViewport`](/api-reference/hooks/use-viewport), etc.
```jsx
import { ReactFlow, useStore } from '@xyflow/react';
const nodesLengthSelector = (state) =>
state.nodes.length || 0;
const NodesLengthDisplay = () => {
const nodesLength = useStore(nodesLengthSelector);
return
The current number of nodes is: {nodesLength}
;
};
function Flow() {
return (
);
}
```
This example computes the number of nodes eagerly. Whenever the number of nodes
in the flow changes, the `` component will re-render. This
is in contrast to the example in the [`useStoreApi`](/api-reference/hooks/use-store-api) hook that only
computes the number of nodes when a button is clicked.
Choosing whether to calculate values on-demand or to subscribe to changes as they
happen is a bit of a balancing act. On the one hand, putting too many heavy
calculations in an event handler can make your app feel sluggish or unresponsive.
On the other hand, computing values eagerly can lead to slow or unnecessary
re-renders.
We make both this hook and [`useStoreApi`](/api-reference/hooks/use-store-api) available so that you
can choose the approach that works best for your use-case.
## Signature
## Examples
### Triggering store actions
You can manipulate the internal React Flow state by triggering internal actions
through the `useStore` hook. These actions are already used internally throughout
the library, but you can also use them to implement custom functionality.
```jsx
import { useStore } from '@xyflow/react';
const setMinZoomSelector = (state) => state.setMinZoom;
function MinZoomSetter() {
const setMinZoom = useStore(setMinZoomSelector);
return ;
}
```
## TypeScript
This hook can be typed by typing the selector function. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const nodes = useStore((s: ReactFlowState) => s.nodes);
```
# useUpdateNodeInternals()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useUpdateNodeInternals.ts)
When you programmatically add or remove handles to a node or update a node's
handle position, you need to let React Flow know about it using this hook. This
will update the internal dimensions of the node and properly reposition handles
on the canvas if necessary.
```jsx
import { useCallback, useState } from 'react';
import { Handle, useUpdateNodeInternals } from '@xyflow/react';
export default function RandomHandleNode({ id }) {
const updateNodeInternals = useUpdateNodeInternals();
const [handleCount, setHandleCount] = useState(0);
const randomizeHandleCount = useCallback(() => {
setHandleCount(Math.floor(Math.random() * 10));
updateNodeInternals(id);
}, [id, updateNodeInternals]);
return (
<>
{Array.from({ length: handleCount }).map((_, index) => (
))}
There are {handleCount} handles on this node.
>
);
}
```
## Signature
## Notes
* This hook can only be used in a component that is a child of a
[``](/api-reference/react-flow-provider) or a
[``](/api-reference/react-flow) component.
# useViewport()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/hooks/useViewport.ts)
The `useViewport` hook is a convenient way to read the current state of the
[`Viewport`](/api-reference/types/viewport) in a component. Components that use this hook
will re-render **whenever the viewport changes**.
```jsx
import { useViewport } from '@xyflow/react';
export default function ViewportDisplay() {
const { x, y, zoom } = useViewport();
return (
The viewport is currently at ({x}, {y}) and zoomed to {zoom}.
);
}
```
## Signature
## Notes
* This hook can only be used in a component that is a child of a
[``](/api-reference/react-flow-provider) or a
[``](/api-reference/react-flow) component.
import { ContentGrid, ContentGridItem } from '@xyflow/xy-ui';
import { BlogPostPreview } from 'xy-shared';
# API Reference
This reference attempts to document every function, hook, component, and type
exported by React Flow. If you are looking for guides and tutorials, please refer to our [learn section](/learn).
## How to use this reference
We think that documentation should answer two broad
questions: "what is this thing?" and "how do I use it?"
To that end, our API reference aims to **concisely** answer that first question
and learn section goes into more detail on the second. If you find yourself clicking
around the reference wondering what the heck any of this means, maybe we have a
guide that can help you out!
## A note for our long-term users
If you're coming here from our old API pages things might look a bit different!
We've reorganized our documentation to make it easier to look things up if you
know what you're looking for. All our types, components, hooks, and util functions
get their own page now to help you find exactly what you need.
If you're new to React Flow or you're not sure where to look for something, take
a look at the section below.
## A note for JavaScript users
React Flow is written in TypeScript, but we know that not everyone uses it. We
encourage developers to use the technology that works best for them, and
throughout our documentation there is a blend of TypeScript and JavaScript
examples.
For our API reference, however, we use TypeScript's syntax to document the types
of props and functions. Here's a quick crash course on how to read it:
• `?` means that the field or argument is optional.
• `` in a type definition represents a generic type parameter. Like a function
argument but for types! The definition `type Array = ...` means a type called
`Array` that takes a generic type parameter `T`.
• `` when referring to a type is like "filling in" a generic type parameter.
It's like calling a function but for types! The type `Array` is the
type `Array` with the generic type parameter `T` filled in with the type
`number`.
• `T | U` means that the type is either `T` or `U`: this is often called a
*union*.
• `T & U` means that the type is both `T` and `U`: this is often called an
*intersection*.
The TypeScript folks have their own
[handy guide for reading types](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html)
that you might find useful. If you're still stuck on something, feel free to
drop by our [Discord](https://discord.com/invite/RVmnytFmGW) and ask for help!
# ======= The ReactFlowProvider component =======
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/ReactFlowProvider/index.tsx/#L9)
The `` component is a
[context provider](https://react.dev/learn/passing-data-deeply-with-context#) that
makes it possible to access a flow's internal state outside of the
[``](/api-reference/react-flow) component. Many of the hooks we
provide rely on this component to work.
```tsx
import { ReactFlow, ReactFlowProvider, useNodes } from '@xyflow/react'
export default function Flow() {
return (
)
}
function Sidebar() {
// This hook will only work if the component it's used in is a child of a
// .
const nodes = useNodes()
return (
)
}
```
## Props
## Notes
* If you're using a router and want your flow's state to persist across routes,
it's vital that you place the `` component *outside* of
your router.
* If you have multiple flows on the same page you will need to use a separate
`` for each flow.
# ======= The ReactFlow component =======
import { ReactFlowAPIProps } from '@/references/ReactFlow.props';
# \
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/container/ReactFlow/index.tsx/#L47)
The `` component is the heart of your React Flow application. It
renders your nodes and edges, handles user interaction, and can manage its own
state if used as an [uncontrolled flow](/learn/advanced-use/uncontrolled-flow).
```tsx
import { ReactFlow } from '@xyflow/react'
export default function Flow() {
return
}
```
This component takes a lot of different props, most of which are optional. We've
tried to document them in groups that make sense to help you find your way.
## Common props
These are the props you will most commonly use when working with React Flow. If
you are working with a controlled flow with custom nodes, you will likely use
almost all of these!
## Viewport props
## Edge props
## Event handlers
> \[!WARNING]
>
> It's important to remember to define any event handlers outside of your
> component or using React's `useCallback` hook. If you don't, this can cause
> React Flow to enter an infinite re-render loop!
### General Events
### Node Events
### Edge Events
### Connection Events
### Pane Events
### Selection Events
## Interaction props
## Connection line props
## Keyboard props
React Flow let's you pass in a few different keyboard shortcuts as another way
to interact with your flow. We've tried to set up sensible defaults like using
backspace to delete any selected nodes or edges, but you can use these props to
set your own.
To disable any of these shortcuts, pass in `null` to the prop you want to
disable.
## Style props
Applying certain classes to elements rendered inside the canvas will change how
interactions are handled. These props let you configure those class names if you
need to.
## Notes
* The props of this component get exported as `ReactFlowProps`
# AriaLabelConfig
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/constants.ts/)
With the `AriaLabelConfig` you can customize the aria labels used by React Flow. This is useful if you want to translate the labels or if you want to change them to better suit your application.
## Fields
## Default config
```js
const defaultAriaLabelConfig = {
'node.a11yDescription.default':
'Press enter or space to select a node. Press delete to remove it and escape to cancel.',
'node.a11yDescription.keyboardDisabled':
'Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.',
'node.a11yDescription.ariaLiveMessage': ({ direction, x, y }: { direction: string; x: number; y: number }) =>
`Moved selected node ${direction}. New position, x: ${x}, y: ${y}`,
'edge.a11yDescription.default':
'Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.',
// Control elements
'controls.ariaLabel': 'Control Panel',
'controls.zoomIn.ariaLabel': 'Zoom In',
'controls.zoomOut.ariaLabel': 'Zoom Out',
'controls.fitView.ariaLabel': 'Fit View',
'controls.interactive.ariaLabel': 'Toggle Interactivity',
// Mini map
'minimap.ariaLabel': 'Mini Map',
// Handle
'handle.ariaLabel': 'Handle',
};
```
# BackgroundVariant
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/additional-components/Background/types.ts)
The three variants are exported as an enum for convenience. You can either import
the enum and use it like `BackgroundVariant.Lines` or you can use the raw string
value directly.
```ts
export enum BackgroundVariant {
Lines = 'lines',
Dots = 'dots',
Cross = 'cross',
}
```
# ColorMode
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts)
The `ColorMode` type defines the available color modes for the ReactFlow component. This can be used to control the theme of the flow diagram.
```ts
export type ColorMode = 'light' | 'dark' | 'system';
```
# ConnectionLineComponentProps
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts/#L193)
If you want to render a custom component for connection lines, you can set the
`connectionLineComponent` prop on the
[``](/api-reference/react-flow#connection-connectionLineComponent) component.
The `ConnectionLineComponentProps` are passed to your custom component.
## Props
# ConnectionLineComponent
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts#L265)
The `ConnectionLineComponent` type allows you to provide a custom React component to render the connection line when users create new edges. The component receives `ConnectionLineComponentProps` as its props.
```ts
type ConnectionLineComponent = React.ComponentType;
```
# ConnectionLineType
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/edges.ts/#L62)
If you set the `connectionLineType` prop on your [``](/api-reference/react-flow#connection-connectionLineType)
component, it will dictate the style of connection line rendered when creating
new edges.
```ts
export enum ConnectionLineType {
Bezier = 'default',
Straight = 'straight',
Step = 'step',
SmoothStep = 'smoothstep',
SimpleBezier = 'simplebezier',
}
```
## Notes
* If you choose to render a custom connection line component, this value will be
passed to your component as part of its [`ConnectionLineComponentProps`](/api-reference/types/connection-line-component-props).
# ConnectionMode
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L68)
The `ConnectionMode` enum provides two options for connection behavior in React Flow:
* `Strict`: Connections can only be made starting from a source handle and ending on a target handle
* `Loose`: Connections can be made between any handles, regardless of type
```ts
enum ConnectionMode {
Strict = 'strict',
Loose = 'loose',
}
```
# ConnectionState
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts/#L148-L174)
The `ConnectionState` type bundles all information about an ongoing connection. It is returned by the [`useConnection`](/api-reference/hooks/use-connection) hook.
```ts
type NoConnection = {
inProgress: false;
isValid: null;
from: null;
fromHandle: null;
fromPosition: null;
fromNode: null;
to: null;
toHandle: null;
toPosition: null;
toNode: null;
};
type ConnectionInProgress = {
inProgress: true;
isValid: boolean | null;
from: XYPosition;
fromHandle: Handle;
fromPosition: Position;
fromNode: NodeBase;
to: XYPosition;
toHandle: Handle | null;
toPosition: Position;
toNode: NodeBase | null;
};
type ConnectionState = ConnectionInProgress | NoConnection;
```
## Fields
# Connection
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts/#L29-L34)
The `Connection` type is the basic minimal description of an
[`Edge`](/api-reference/types/edge) between two nodes. The
[`addEdge`](/api-reference/utils/add-edge) util can be used to upgrade a `Connection` to
an [`Edge`](/api-reference/types/edge).
## Fields
# CoordinateExtent
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/utils.ts/#L36-L37)
A coordinate extent represents two points in a coordinate system: one in the top
left corner and one in the bottom right corner. It is used to represent the
bounds of nodes in the flow or the bounds of the viewport.
```ts
export type CoordinateExtent = [[number, number], [number, number]];
```
## Notes
* Props that expect a `CoordinateExtent` usually default to `[[-∞, -∞], [+∞, +∞]]`
to represent an unbounded extent.
# DefaultEdgeOptions
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts/#L88-L89)
Many properties on an [`Edge`](/api-reference/types/edge) are optional. When a new edge is
created, the properties that are not provided will be filled in with the default values
passed to the `defaultEdgeOptions` prop of the
[``](/api-reference/react-flow#defaultedgeoptions) component.
## Fields
# DeleteElements
DeleteElements deletes provided nodes and edges and handles deleting any connected edges as well as child nodes. Returns successfully deleted edges and nodes asynchronously.
```ts
export type DeleteElements = (payload: {
nodes?: (Partial & { id: Node['id'] })[];
edges?: (Partial & { id: Edge['id'] })[];
}) => Promise<{
deletedNodes: Node[];
deletedEdges: Edge[];
}>;
```
# EdgeChange
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/changes.ts/#L68-L72)
The [`onEdgesChange`](/api-reference/react-flow#on-edges-change) callback takes
an array of `EdgeChange` objects that you should use to update your flow's state.
The `EdgeChange` type is a union of four different object types that represent that
various ways an edge can change in a flow.
```ts
export type EdgeChange =
| EdgeAddChange
| EdgeRemoveChange
| EdgeReplaceChange
| EdgeSelectionChange;
```
## Variants
### EdgeAddChange
### EdgeRemoveChange
### EdgeReplaceChange
### EdgeSelectionChange
# EdgeMarker
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/edges.ts/#L70-L78)
Edges can optionally have markers at the start and end of an edge. The `EdgeMarker` type
is used to configure those markers! Check the docs for
[`MarkerType`](/api-reference/types/marker-type) for details on what types of edge marker
are available.
## Fields
# EdgeMouseHandler
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts#L81)
The `EdgeMouseHandler` type defines the callback function that is called when mouse events occur on an edge. This callback receives the event and the edge that triggered it.
```ts
type EdgeMouseHandler = (event: React.MouseEvent, edge: Edge) => void;
```
# EdgeProps
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts/#L100)
When you implement a custom edge it is wrapped in a component that enables some basic
functionality. The `EdgeProps` type takes a generic parameter to specify the type of edges
you use in your application:
```ts
type AppEdgeProps = EdgeProps;
```
Your custom edge component receives the following props:
## Fields
# EdgeTypes
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#L76)
The `EdgeTypes` type is used to define custom edge types. Each key in the object represents an edge type, and the value is the component that should be rendered for that type.
```ts
export type EdgeTypes = {
[key: string]: React.ComponentType;
};
```
# Edge
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts/#L34-L353)
Where a [`Connection`](/api-reference/types/connection) is the minimal description of an edge between
two nodes, an `Edge` is the complete description with everything React Flow needs
to know in order to render it.
```ts
export type Edge = DefaultEdge | SmoothStepEdge | BezierEdge;
```
## Variants
### Edge
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts/#L34-L353)
### SmoothStepEdge
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts/#L45-L46)
The `SmoothStepEdge` variant has all the same fields as an `Edge`, but it also has the following additional fields:
{/* type SmoothStepEdge isn't exported, and conflicts with SmoothStepEdge component name */}
### BezierEdge
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/edges.ts/#L52-L53)
The `BezierEdge` variant has all the same fields as an `Edge`, but it also has the following additional fields:
{/* type BezierEdge isn't exported, and conflicts with BezierEdge component name */}
## Default edge types
You can create any of React Flow's default edges by setting the `type` property
to one of the following values:
* `"default"`
* `"straight"`
* `"step"`
* `"smoothstep"`
* `"simplebezier"`
If you don't set the `type` property at all, React Flow will fallback to the
`"default"` bezier curve edge type.
These default edges are available even if you set the [`edgeTypes`](/api-reference/react-flow#edge-types)
prop to something else, unless you override any of these keys directly.
# FitViewOptions
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts/#L67-L68)
When calling [`fitView`](/api-reference/types/react-flow-instance#fitview) these options
can be used to customize the behavior. For example, the `duration` option can be used to
transform the viewport smoothly over a given amount of time.
## Fields
# HandleConnection
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts/#L36-L37)
The `HandleConnection` type is an extension of a basic
[Connection](/api-reference/types/connection) that includes the `edgeId`.
## Fields
# Handle
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/handles.ts/#L5)
The `Handle` type represents the attributes of a handle.
## Fields
import { ApiReferenceSummary } from 'xy-shared/server';
# Types
# InternalNode
[Source on GitHub](https://github.com/xyflow/xyflow/blob/99985b52026cf4ac65a1033178cf8c2bea4e14fa/packages/system/src/types/nodes.ts#L68)
The `InternalNode` type is identical to the base [`Node`](/api-references/types/node) type
but is extended with some additional properties used internally by React Flow. Some
functions and callbacks that return nodes may return an `InternalNode`.
## Fields
# IsValidConnection
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#L212)
The `IsValidConnection` type represents a function that validates whether a connection between nodes is allowed. It receives a [`Connection`](/api-reference/types/connection) and returns a boolean indicating whether the connection is valid and therefore should be created.
```ts
type IsValidConnection = (edge: Edge | Connection) => boolean;
```
# KeyCode
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L155)
The `KeyCode` type is used to specify keyboard key codes or combinations, such as deleting nodes or enabling multi-selection. It can be a single string or an array of strings representing key codes.
```ts
type KeyCode = string | Array;
```
# MarkerType
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/edges.ts/#L82-L83)
Edges may optionally have a marker on either end. The MarkerType type enumerates
the options available to you when configuring a given marker.
```ts
export enum MarkerType {
Arrow = 'arrow',
ArrowClosed = 'arrowclosed',
}
```
# MiniMapNodeProps
[Source on GitHub](https://github.com/xyflow/xyflow/blob/487b13c9ad8903789f56c6fcfd8222f9cb74b812/packages/react/src/additional-components/MiniMap/types.ts/#L60)
The MiniMapNodeProps type defines the props for nodes in the MiniMap component. This is
only relevant if you pass a custom node type to the MiniMap.
## Fields
```
```
# NodeChange
[Source on GitHub](https://github.com/xyflow/xyflow/blob/487b13c9ad8903789f56c6fcfd8222f9cb74b812/packages/system/src/types/changes.ts/#L47)
The [`onNodesChange`](/api-reference/react-flow#on-nodes-change) callback takes
an array of `NodeChange` objects that you should use to update your flow's state.
The `NodeChange` type is a union of six different object types that represent that
various ways an node can change in a flow.
```ts
export type NodeChange =
| NodeDimensionChange
| NodePositionChange
| NodeSelectionChange
| NodeRemoveChange
| NodeAddChange
| NodeReplaceChange;
```
## Variant types
### NodeDimensionChange
### NodePositionChange
### NodeSelectionChange
### NodeRemoveChange
### NodeAddChange
### NodeReplaceChange
# NodeConnection
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts/#L36-L37)
The `NodeConnection` type is an extension of a basic
[Connection](/api-reference/types/connection) that includes the `edgeId`.
## Fields
# NodeHandle
[Source on GitHub](https://github.com/xyflow/xyflow/blob/13897512d3c57e72c2e27b14ffa129412289d948/packages/system/src/types/nodes.ts#L139)
The `NodeHandle` type is used to define a handle for a node if server-side rendering is used. On the server, React Flow can't measure DOM nodes, so it's necessary to define the handle position dimensions.
# NodeMouseHandler
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/nodes.tsL32)
The `NodeMouseHandler` type defines the callback function that is called when mouse events occur on a node. This callback receives the event and the node that triggered it.
```ts
export type NodeMouseHandler = (event: React.MouseEvent, node: Node) => void;
```
# NodeOrigin
The origin of a Node determines how it is placed relative to its own coordinates.
`[0, 0]` places it at the top left corner, `[0.5, 0.5]` right in the center and `[1, 1]` at the bottom right of its position.
```ts
export type NodeOrigin = [number, number];
```
# ======= NodeProps =======
# NodeProps\
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/nodes.ts/#L89)
When you implement a [custom node](/learn/customization/custom-nodes) it is wrapped in a
component that enables basic functionality like selection and dragging.
## Usage
```tsx
import { useState } from 'react';
import { NodeProps, Node } from '@xyflow/react';
export type CounterNode = Node<
{
initialCount?: number;
},
'counter'
>;
export default function CounterNode(props: NodeProps) {
const [count, setCount] = useState(props.data?.initialCount ?? 0);
return (
Count: {count}
);
}
```
Remember to register your custom node by adding it to the
[`nodeTypes`](/api-reference/react-flow#nodetypes) prop of your `` component.
```tsx
import { ReactFlow } from '@xyflow/react';
import CounterNode from './CounterNode';
const nodeTypes = {
counterNode: CounterNode,
};
export default function App() {
return
}
```
You can read more in our [custom node guide](/learn/customization/custom-nodes).
## Fields
Your custom node receives the following props:
# NodeTypes
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/nodes.ts)
The `NodeTypes` type is used to define custom node types. Each key in the object represents a node type, and the value is the component that should be rendered for that type.
```ts
type NodeTypes = {
[key: string]: React.ComponentType;
};
```
# Node
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/nodes.ts/#L10)
The `Node` type represents everything React Flow needs to know about a given node.
Many of these properties can be manipulated both by React Flow or by you, but
some such as `width` and `height` should be considered read-only.
## Fields
## Default node types
You can create any of React Flow's default nodes by setting the `type` property
to one of the following values:
* `"default"`
* `"input"`
* `"output"`
* `"group"`
If you don't set the `type` property at all, React Flow will fallback to the
`"default"` node with both an input and output port.
These default nodes are available even if you set the [`nodeTypes`](/api-reference/react-flow#node-types)
prop to something else, unless you override any of these keys directly.
## Notes
* You shouldn't try to set the `width` or `height` of a node directly. It is
calculated internally by React Flow and used when rendering the node in the
viewport. To control a node's size you should use the `style` or `className`
props to apply CSS styles instead.
# OnBeforeDelete
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#L207)
The `OnBeforeDelete` type defines the callback function that is called before nodes or edges are deleted. This callback receives an object containing the nodes and edges that are about to be deleted.
```ts
type OnBeforeDelete = (params: {
nodes: Node[];
edges: Edge[];
}) => Promise;
```
# OnConnectEnd
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L89)
The `OnConnectEnd` type represents a callback function that is called when finishing or canceling a connection attempt. It receives the mouse or touch event and the final state of the connection attempt.
```ts
type OnConnectEnd = (
event: MouseEvent | TouchEvent,
connectionState: FinalConnectionState,
) => void;
```
# OnConnectStart
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L79)
The `OnConnectStart` type represents a callback function that is called when starting to create a connection between nodes. It receives the mouse or touch event and information about the source node and handle.
```ts
type OnConnectStart = (
event: MouseEvent | TouchEvent,
params: OnConnectStartParams,
) => void;
```
# OnConnect
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L80)
The `OnConnect` type represents a callback function that is called when a new connection is created between nodes. It receives a [`Connection`](/api-reference/types/connection) containing the source and target node IDs and their respective handle IDs.
```ts
type OnConnect = (connection: Connection) => void;
```
# OnDelete
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#L59)
The `OnDelete` type defines the callback function that is called when nodes or edges are deleted. This callback receives an object containing the deleted nodes and edges.
```ts
type OnDelete = (params: { nodes: Node[]; edges: Edge[] }) => void;
```
# OnEdgesChange
This type is used for typing the [`onEdgesChange`](/api-reference/react-flow#on-edges-change) function.
```tsx
export type OnEdgesChange = (
changes: EdgeChange[],
) => void;
```
## Fields
## Usage
This type accepts a generic type argument of custom edge types. See this
[section in our Typescript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const onEdgesChange: OnEdgesChange = useCallback(
(changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
[setEdges],
);
```
# OnEdgesDelete
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#L52)
The `OnEdgesDelete` type defines the callback function that is called when edges are deleted. This callback receives an array of the deleted edges.
```ts
type OnEdgesDelete = (edges: Edge[]) => void;
```
# OnError
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L233)
The `OnError` type defines the callback function that is called when an error occurs. This callback receives an error id and the error message as its argument.
```ts
type OnError = (id: string, error: string) => void;
```
# OnInit
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#L113)
The `OnInit` type defines the callback function that is called when the ReactFlow instance is initialized. This callback receives the ReactFlow instance as its argument.
```ts
type OnInit = (reactFlowInstance: ReactFlowInstance) => void;
```
# OnMove
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L16)
The `OnMove` type is a callback that fires whenever the viewport is moved, either by user interaction or programmatically. It receives the triggering event and the new viewport state.
```ts
type OnMove = (event: MouseEvent | TouchEvent | null, viewport: Viewport) => void;
```
# OnNodeDrag
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/nodes.ts#L34)
The `OnNodeDrag` type defines the callback function that is called when a node is being dragged. This callback receives the event and the node that is being dragged.
```ts
type OnNodeDrag = (event: React.MouseEvent, node: Node) => void;
```
# OnNodesChange
This type is used for typing the [`onNodesChange`](/api-reference/react-flow#on-nodes-change) function.
```tsx
export type OnNodesChange = (
changes: NodeChange[],
) => void;
```
## Fields
## Usage
This type accepts a generic type argument of custom nodes types. See this
[section in our TypeScript guide](/learn/advanced-use/typescript#nodetype-edgetype-unions) for more information.
```tsx
const onNodesChange: OnNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[setNodes],
);
```
# OnNodesDelete
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#L51)
The `OnNodesDelete` type defines the callback function that is called when nodes are deleted. This callback receives an array of the deleted nodes.
```ts
type OnNodesDelete = (nodes: Node[]) => void;
```
# OnReconnect
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L83)
The `OnReconnect` type represents a callback function that is called when an existing edge is reconnected to a different node or handle. It receives the old edge and the new connection details.
```ts
type OnReconnect = (
oldEdge: EdgeType,
newConnection: Connection,
) => void;
```
# OnSelectionChangeFunc
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/general.ts#98)
The `OnSelectionChangeFunc` type is a callback that is triggered when the selection of nodes or edges changes. It receives an object containing the currently selected nodes and edges.
```ts
type OnSelectionChangeFunc = (params: { nodes: Node[]; edges: Edge[] }) => void;
```
# PanOnScrollMode
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L166)
The `PanOnScrollMode` enum controls the panning behavior of the viewport when the user scrolls. Choose `Free` for unrestricted panning, `Vertical` for up-and-down only, or `Horizontal` for left-and-right only.
```ts
enum PanOnScrollMode {
Free = 'free',
Vertical = 'vertical',
Horizontal = 'horizontal',
}
```
# PanelPosition
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts/#L111-L112)
This type is mostly used to help position things on top of the flow viewport. For
example both the [``](/api-reference/components/minimap) and
[``](/api-reference/components/controls) components take a `position`
prop of this type.
```ts
export type PanelPosition =
| 'top-left'
| 'top-center'
| 'top-right'
| 'bottom-left'
| 'bottom-center'
| 'bottom-right'
| 'center-left'
| 'center-right';
```
# Position
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/utils.ts/#L1)
While [`PanelPosition`](/api-reference/types/panel-position) can be used to place a component in the
corners of a container, the `Position` enum is less precise and used primarily
in relation to edges and handles.
```ts
export enum Position {
Left = 'left',
Top = 'top',
Right = 'right',
Bottom = 'bottom',
}
```
# ProOptions
By default, we render a small attribution in the corner of your flows that links back to
the project. Anyone is free to remove this attribution whether they're a Pro subscriber or
not but we ask that you take a quick look at our
[removing attribution](/learn/troubleshooting/remove-attribution) guide before doing so.
import {
NodesAndEdgesFields,
IntersectionFields,
ViewportFields,
} from '@/references/react-flow-instance';
# ReactFlowInstance
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/instance.ts/#L178-L179)
The `ReactFlowInstance` provides a collection of methods to query and manipulate the
internal state of your flow. You can get an instance by using the
[`useReactFlow`](/api-reference/hooks/use-react-flow) hook or attaching a listener to the
[`onInit`](/api-reference/react-flow#event-oninit) event.
## Fields
### Nodes and edges
### Intersections
### Viewport
# ReactFlowJsonObject
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/instance.ts/#L5)
A JSON-compatible representation of your flow. You can use this to save the flow to a
database for example and load it back in later.
## Fields
# Rect
[Source on GitHub](https://github.com/xyflow/xyflow/blob/f0ce2c876d8688e13632bc86286cf857f86dead6/packages/system/src/types/utils.ts/#L39-L40)
The `Rect` type defines a rectangle in a two-dimensional space with dimensions and a
position.
# ResizeParams
[Source on Github](https://github.com/xyflow/xyflow/blob/v11/packages/node-resizer/src/types.ts/#L4)
The `ResizeParams` type is used to type the various events that are emitted by the
`` component. You'll sometimes see this type extended with an additional
direction field too.
## Fields
# SelectionDragHandler
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/types/nodes.ts#L33)
The `SelectionDragHandler` type is a callback for handling drag events involving selected nodes. It receives the triggering mouse or touch event and an array of the affected nodes.
```ts
type SelectionDragHandler = (
event: ReactMouseEvent,
nodes: NodeType[],
) => void;
```
# SelectionMode
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L223)
The `SelectionMode` enum provides two options for node selection behavior:
* `Full`: A node is only selected when the selection rectangle fully contains it
* `Partial`: A node is selected when the selection rectangle partially overlaps with it
```ts
enum SelectionMode {
Partial = 'partial',
Full = 'full',
}
```
# SnapGrid
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts#L157)
The `SnapGrid` type defines the grid size for snapping nodes on the pane. It is used in conjunction with the `snapToGrid` prop to enable grid snapping functionality.
```ts
type SnapGrid = [number, number];
```
# Viewport
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/types/general.ts/#L149-L153)
Internally, React Flow maintains a coordinate system that is independent of the rest of
the page. The `Viewport` type tells you where in that system your flow is currently being
display at and how zoomed in or out it is.
## Fields
## Notes
* A `Transform` has the same properties as the viewport, but they represent different
things. Make sure you don't get them muddled up or things will start to look weird!
# XYPosition
All positions are stored in an object with x and y coordinates.
```ts
export type XYPosition = {
x: number;
y: number;
};
```
# addEdge()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/edges/general.ts/#L100)
This util is a convenience function to add a new [`Edge`](/api-reference/types/edge) to an
array of edges. It also performs some validation to make sure you don't add an
invalid edge or duplicate an existing one.
```js
import { useCallback } from 'react';
import {
ReactFlow,
addEdge,
useNodesState,
useEdgesState,
} from '@xyflow/react';
export default function Flow() {
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const onConnect = useCallback(
(connection) => {
setEdges((oldEdges) => addEdge(connection, oldEdges));
},
[setEdges],
);
return ;
}
```
## Signature
## Notes
* If an edge with the same `target` and `source` already exists (and the same
`targetHandle` and `sourceHandle` if those are set), then this util won't add
a new edge even if the `id` property is different.
# applyEdgeChanges()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/utils/changes.ts/#L167)
Various events on the [``](/api-reference/react-flow) component can produce an
[`EdgeChange`](/api-reference/types/edge-change) that describes how to update the edges of your
flow in some way. If you don't need any custom behavior, this util can be used to
take an array of these changes and apply them to your edges.
```js
import { useState, useCallback } from 'react';
import { ReactFlow, applyEdgeChanges } from '@xyflow/react';
export default function Flow() {
const [nodes, setNodes] = useState([]);
const [edges, setEdges] = useState([]);
const onEdgesChange = useCallback(
(changes) => {
setEdges((oldEdges) => applyEdgeChanges(changes, oldEdges));
},
[setEdges],
);
return (
);
}
```
## Signature
## Notes
* If you don't need any custom behavior, the [`useEdgesState`](/api-reference/hooks/use-edges-state)
hook conveniently wraps this util and React's `useState` hook for you and might
be simpler to use.
# applyNodeChanges()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/react/src/utils/changes.ts/#L140)
Various events on the [``](/api-reference/react-flow) component can produce a
[`NodeChange`](/api-reference/types/node-change) that describes how to update the nodes of your
flow in some way. If you don't need any custom behavior, this util can be used to
take an array of these changes and apply them to your nodes.
```js
import { useState, useCallback } from 'react';
import { ReactFlow, applyNodeChanges } from '@xyflow/react';
export default function Flow() {
const [nodes, setNodes] = useState([]);
const [edges, setEdges] = useState([]);
const onNodesChange = useCallback(
(changes) => {
setNodes((oldNodes) => applyNodeChanges(changes, oldNodes));
},
[setNodes],
);
return (
);
}
```
## Signature
## Notes
* If you don't need any custom behavior, the [`useNodesState`](/api-reference/hooks/use-nodes-state)
hook conveniently wraps this util and React's `useState` hook for you and might
be simpler to use.
# getBezierPath()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/edges/bezier-edge.ts/#L95)
The `getBezierPath` util returns everything you need to render a bezier edge
between two nodes.
```js
import { Position, getBezierPath } from '@xyflow/react';
const source = { x: 0, y: 20 };
const target = { x: 150, y: 100 };
const [path, labelX, labelY, offsetX, offsetY] = getBezierPath({
sourceX: source.x,
sourceY: source.y,
sourcePosition: Position.Right,
targetX: target.x,
targetY: target.y,
targetPosition: Position.Left,
});
console.log(path); //=> "M0,20 C75,20 75,100 150,100"
console.log(labelX, labelY); //=> 75, 60
console.log(offsetX, offsetY); //=> 75, 40
```
## Signature
## Notes
* This function returns a tuple (aka a fixed-size array) to make it easier to
work with multiple edge paths at once.
# getConnectedEdges()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/graph.ts/#L224)
This utility filters an array of edges, keeping only those where either the source or target node is present in the given array of nodes.
```js
import { getConnectedEdges } from '@xyflow/react';
const nodes = [
{ id: 'a', position: { x: 0, y: 0 } },
{ id: 'b', position: { x: 100, y: 0 } },
];
const edges = [
{ id: 'a->c', source: 'a', target: 'c' },
{ id: 'c->d', source: 'c', target: 'd' },
];
const connectedEdges = getConnectedEdges(nodes, edges);
// => [{ id: 'a->c', source: 'a', target: 'c' }]
```
## Signature
# getIncomers()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/graph.ts/#L91)
This util is used to tell you what nodes, if any, are connected to the given node
as the *source* of an edge.
```ts
import { getIncomers } from '@xyflow/react';
const nodes = [];
const edges = [];
const incomers = getIncomers(
{ id: '1', position: { x: 0, y: 0 }, data: { label: 'node' } },
nodes,
edges,
);
```
## Signature
# getNodesBounds()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/graph.ts/#L133)
Returns the bounding box that contains all the given nodes in an array. This can
be useful when combined with [`getViewportForBounds`](/api-reference/utils/get-viewport-for-bounds)
to calculate the correct transform to fit the given nodes in a viewport.
> \[!NOTE]
>
> This function was previously called `getRectOfNodes`
```js
import { getNodesBounds } from '@xyflow/react';
const nodes = [
{
id: 'a',
position: { x: 0, y: 0 },
data: { label: 'a' },
width: 50,
height: 25,
},
{
id: 'b',
position: { x: 100, y: 100 },
data: { label: 'b' },
width: 50,
height: 25,
},
];
const bounds = getNodesBounds(nodes);
```
## Signature
# getOutgoers()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/graph.ts/#L64)
This util is used to tell you what nodes, if any, are connected to the given node
as the *target* of an edge.
```ts
import { getOutgoers } from '@xyflow/react';
const nodes = [];
const edges = [];
const outgoers = getOutgoers(
{ id: '1', position: { x: 0, y: 0 }, data: { label: 'node' } },
nodes,
edges,
);
```
## Signature
# getSimpleBezierPath()
[Source on Github](https://github.com/xyflow/xyflow/blob/main/packages/react/src/components/Edges/SimpleBezierEdge.tsx/#L32)
The `getSimpleBezierPath` util returns everything you need to render a simple
bezier edge between two nodes.
```js
import { Position, getSimpleBezierPath } from '@xyflow/react';
const source = { x: 0, y: 20 };
const target = { x: 150, y: 100 };
const [path, labelX, labelY, offsetX, offsetY] = getSimpleBezierPath({
sourceX: source.x,
sourceY: source.y,
sourcePosition: Position.Right,
targetX: target.x,
targetY: target.y,
targetPosition: Position.Left,
});
console.log(path); //=> "M0,20 C75,20 75,100 150,100"
console.log(labelX, labelY); //=> 75, 60
console.log(offsetX, offsetY); //=> 75, 40
```
## Signature
## Notes
* This function returns a tuple (aka a fixed-size array) to make it easier to
work with multiple edge paths at once.
# getSmoothStepPath()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/edges/smoothstep-edge.ts/#L215)
The `getSmoothStepPath` util returns everything you need to render a stepped path
between two nodes. The `borderRadius` property can be used to choose how rounded
the corners of those steps are.
```js
import { Position, getSmoothStepPath } from '@xyflow/react';
const source = { x: 0, y: 20 };
const target = { x: 150, y: 100 };
const [path, labelX, labelY, offsetX, offsetY] = getSmoothStepPath({
sourceX: source.x,
sourceY: source.y,
sourcePosition: Position.Right,
targetX: target.x,
targetY: target.y,
targetPosition: Position.Left,
});
console.log(path); //=> "M0 20L20 20L 70,20Q 75,20 75,25L 75,95Q ..."
console.log(labelX, labelY); //=> 75, 60
console.log(offsetX, offsetY); //=> 75, 40
```
## Signature
## Notes
* This function returns a tuple (aka a fixed-size array) to make it easier to
work with multiple edge paths at once.
* You can set the `borderRadius` property to `0` to get a step edge path.
# getStraightPath()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/edges/straight-edge.ts/#L30)
Calculates the straight line path between two points.
```js
import { getStraightPath } from '@xyflow/react';
const source = { x: 0, y: 20 };
const target = { x: 150, y: 100 };
const [path, labelX, labelY, offsetX, offsetY] = getStraightPath({
sourceX: source.x,
sourceY: source.y,
targetX: target.x,
targetY: target.y,
});
console.log(path); //=> "M 0,20L 150,100"
console.log(labelX, labelY); //=> 75, 60
console.log(offsetX, offsetY); //=> 75, 40
```
## Signature
## Notes
* This function returns a tuple (aka a fixed-size array) to make it easier to work with multiple edge paths at once.
import { Callout } from 'nextra/components';
# getViewportForBounds()
[Source on Github](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/general.ts/#L170)
This util returns the viewport for the given bounds.
You might use this to pre-calculate the viewport for a given set of nodes on the
server or calculate the viewport for the given bounds *without* changing the
viewport directly.
> \[!NOTE]
>
> This function was previously called `getTransformForBounds`
```js
import { getViewportForBounds } from '@xyflow/react';
const { x, y, zoom } = getViewportForBounds(
{
x: 0,
y: 0,
width: 100,
height: 100,
},
1200,
800,
0.5,
2,
);
```
## Signature
## Notes
* This is quite a low-level utility. You might want to look at the
[`fitView`](/api-reference/types/react-flow-instance#fitview) or
[`fitBounds`](/api-reference/types/react-flow-instance#fitbounds) methods for a more practical
api.
import { ApiReferenceSummary } from 'xy-shared/server';
# Utils
# isEdge()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/graph.ts/#L39-L40)
Test whether an object is usable as an [`Edge`](/api-reference/types/edge). In TypeScript
this is a type guard that will narrow the type of whatever you pass in to
[`Edge`](/api-reference/types/edge) if it returns `true`.
```js
import { isEdge } from '@xyflow/react';
const edge = {
id: 'edge-a',
source: 'a',
target: 'b',
};
if (isEdge(edge)) {
// ...
}
```
## Signature
# isNode()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/system/src/utils/graph.ts/#L49)
Test whether an object is usable as a [`Node`](/api-reference/types/node). In TypeScript
this is a type guard that will narrow the type of whatever you pass in to
[`Node`](/api-reference/types/node) if it returns `true`.
```js
import { isNode } from '@xyflow/react';
const node = {
id: 'node-a',
data: {
label: 'node',
},
position: {
x: 0,
y: 0,
},
};
if (isNode(node)) {
// ..
}
```
## Signature
# reconnectEdge()
[Source on GitHub](https://github.com/xyflow/xyflow/blob/main/packages/core/src/utils/graph.ts/#L97)
A handy utility to update an existing [`Edge`](/api-reference/types/edge) with new properties.
This searches your edge array for an edge with a matching `id` and updates its
properties with the connection you provide.
```js
const onReconnect = useCallback(
(oldEdge: Edge, newConnection: Connection) => setEdges((els) => reconnectEdge(oldEdge, newConnection, els)),
[]
);
```
## Signature
# ==================================
# Learn
# ==================================
import { Callout } from 'nextra/components';
# Accessibility
If you have suggestions for how we can improve the accessibility of React Flow, please feel free to [contact us](https://xyflow.com/contact).
React Flow provides keyboard and screen-reader support to help meet accessibility standards. By default, all nodes and edges are keyboard-focusable and operable. You can enable or disable these features with props including: [nodesFocusable](/api-reference/react-flow#nodesfocusable), [edgesFocusable](/api-reference/react-flow#edgesfocusable), and [disableKeyboardA11y](/api-reference/react-flow#disablekeyboarda11y) which are passed through `` like this:
```js
{/* ...other components like Controls, MiniMap... */}
```
## Built-in features
* **Tab navigation:** Pressing `Tab` moves focus through all focusable nodes and edges. These elements receive `tabIndex={0}` and, by default, `role="group"` to handle interactivity.
* **Select/Deselect:** Press `Enter` or `Space` to select the focused node/edge, and `Escape` to clear the selection.
* **Move nodes with arrow keys:** If `nodesDraggable` and `nodesFocusable` are both true (default), you can move the selected node with the arrow keys. You can hold `Shift` to increase movement speed. If you set `disableKeyboardA11y={true}`, arrow-key movement is disabled (but tab-focus and selection still work).
* **Automatic panning:** When a node receives focus, React Flow automatically pans the canvas to bring that node into view. This ensures focused nodes are visible to the user. This behavior can be toggled via the [autoPanOnNodeFocus](/api-reference/react-flow#autopanonnodefocus) prop.
* **ARIA descriptions:** React Flow automatically adds ARIA descriptions for keyboard guidance. These can be configured by using [ariaLabelConfig](/api-reference/react-flow#arialabelconfig).
To enable full keyboard accessibility, ensure both `nodesFocusable` and `edgesFocusable`
are set to `true`. If either is false, corresponding elements will not be
keyboard-focusable.
## ARIA roles for nodes and edges
By default, React Flow uses semantic ARIA roles for interactive elements. You can override a node’s role using the `ariaRole` prop. For example:
```js
const nodes = [
{
id: '1',
data: { label: 'Hello' },
ariaRole: 'button',
},
];
;
```
By, default, if you don’t set a role, `role="group"` is applied. Customizing `ariaRole` lets you match any relevant ARIA role (e.g. `"listitem"`, `"region"`, etc.), improving semantic information for assistive technology.
**Note:** The `ariaRole` is applied to the node wrapper. If a custom node includes interactive elements, avoid setting `ariaRole: 'button'` on the node itself. Instead, apply the appropriate ARIA role directly to the interactive element.
### DOM attributes
To pass custom ARIA attributes or other DOM-level attributes (e.g., `aria-roledescription`, `data-\*`,`tabIndex`, etc.), you can use the `domAttributes` prop. This is available for both nodes and edges:
```
// Example for a node
{
id: '2',
data: { label: 'Accessible Node' },
domAttributes: {
'aria-roledescription': 'collapsible node',
tabIndex: 0,
'data-test-id': 'node-2',
},
}
```
This gives you full control over accessibility-related attributes while maintaining React Flow’s built-in roles and behaviors.
## Localizing accessibility messages
React Flow’s built-in accessibility text (such as keyboard instructions and live updates) can be customized or localized via the [ariaLabelConfig](/api-reference/react-flow#arialabelconfig) prop on``. This prop takes an object mapping message keys to strings or functions. Keys include:
| Key | Default Value |
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `node.a11yDescription.default` | Press enter or space to select a node. Press delete to remove it and escape to cancel. |
| `node.a11yDescription.keyboardDisabled` | Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. |
| `node.a11yDescription.ariaLiveMessage` | `Moved selected node {direction}. New position, x: {x}, y: {y}` |
| `edge.a11yDescription.default` | Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. |
| `controls.ariaLabel` | Control Panel |
| `controls.zoomIn.ariaLabel` | Zoom In |
| `controls.zoomOut.ariaLabel` | Zoom Out |
| `controls.fitView.ariaLabel` | Fit View |
| `controls.interactive.ariaLabel` | Toggle Interactivity |
| `minimap.ariaLabel` | Mini Map |
| `handle.ariaLabel` | Handle |
For example, to provide custom or localized text:
```js
const ariaLabels = {
'node.a11yDescription.default': 'Press [Enter] to select this node',
'node.a11yDescription.keyboardDisabled': 'Keyboard navigation is disabled',
};
;
```
This tells React Flow to use your text instead of the defaults. By supplying localized strings via [ariaLabelConfig](/api-reference/react-flow#arialabelconfig), you ensure screen readers announce messages in the user’s language.
## WCAG 2.1 AA
React Flow provides features that can help you meet key WCAG 2.1 AA criteria when properly implemented:
* **Keyboard:** React Flow supports keyboard operability with `Tab` navigation to nodes and edges, interaction via `Enter`/`Space`, and arrow key movement for nodes. These features help satisfy requirements for keyboard accessibility.
* **Screen Reader:** With semantic ARIA roles and labels (e.g. `role="group"`, `aria-label`, and `aria-roledescription`), React Flow enables you to create meaningfully announced graphical nodes/edges. Edge components include a customizable `aria-label` and nodes can be given appropriate `aria-label` text.
* **ARIA Live Regions:** Dynamic updates are announced through an `aria-live` region. The `A11yDescriptions` component includes an element with `aria-live="assertive"` that notifies users of node movements, helping you meet requirements for status messages.
* **Instructions and Focus Management:** React Flow provides contextual help with clear instructions like "Press enter or space to select a node…". The automatic focus management ensures nodes scroll into view when focused, helping satisfy requirements for input assistance.
This guide is helpful for learning about [ARIA best practices](https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/).
# Computing Flows
import { Callout } from 'nextra/components';
import { RemoteCodeViewer } from 'xy-shared/server';
For this guide we assume that you already know about the [core
concepts](/learn/concepts/core-concepts) of React Flow and how to implement
[custom nodes](/learn/customization/custom-nodes).
Usually with React Flow, developers handle their data outside of React Flow by sending it somewhere else, like on a server or a database. Instead, in this guide we'll show you how to compute data flows directly inside of React Flow. You can use this for updating a node based on connected data, or for building an app that runs entirely inside the browser.
## What are we going to build?
By the end of this guide, you will build an interactive flow graph that generates a color out of three separate number input fields (red, green and blue), and determines whether white or black text would be more readable on that background color.
## Creating custom nodes
Let's start by creating a custom input node (`NumberInput.js`) and add three instances of it. We will be using a controlled `` and limit it to integer numbers between 0 - 255 inside the `onChange` event handler.
```jsx
import { useCallback, useState } from 'react';
import { Handle, Position } from '@xyflow/react';
function NumberInput({ id, data }) {
const [number, setNumber] = useState(0);
const onChange = useCallback((evt) => {
const cappedNumber = Math.round(
Math.min(255, Math.max(0, evt.target.value)),
);
setNumber(cappedNumber);
}, []);
return (
{data.label}
);
}
export default NumberInput;
```
Next, we'll add a new custom node (`ColorPreview.js`) with one target handle for each color channel and a background that displays the resulting color. We can use `mix-blend-mode: 'difference';` to make the text color always readable.
Whenever you have multiple handles of the same kind on a single node, don't
forget to give each one a separate id!
Let's also add edges going from the input nodes to the color node to our
`initialEdges` array while we are at it.
## Computing data
How do we get the data from the input nodes to the color node? This is a two step process that involves two hooks created for this exact purpose:
1. Store each number input value inside the node's `data` object with help of the [`updateNodeData`](/api-reference/types/react-flow-instance#update-node-data) callback.
2. Find out which nodes are connected by using [`useNodeConnections`](/api-reference/hooks/use-node-connections) and then use [`useNodesData`](/api-reference/hooks/use-nodes-data) for receiving the data from the connected nodes.
### Step 1: Writing values to the data object
First let's add some initial values for the input nodes inside the `data` object in our `initialNodes` array and use them as an initial state for the input nodes.
Then we'll grab the function [`updateNodeData`](/api-reference/types/react-flow-instance#update-node-data) from the [`useReactFlow`](/api-reference/hooks/use-react-flow) hook and use it to update the `data` object of the node with a new value whenever the input changes.
By default, the data you pass to [`updateNodeData`](/api-reference/types/react-flow-instance#update-node-data) will be merged with the old data object. This makes it easier to do partial updates and saves you in case you forget to add `{...data}`. You can pass `{ replace: true }` as an option to replace the object instead.
When dealing with input fields you don't want to use a nodes `data` object
as UI state directly.
There is a delay in updating the data object and the cursor might jump around
erratically and lead to unwanted inputs.
### Step 2: Getting data from connected nodes
We start by determining all connections for each node with the [`useNodeConnections`](/api-reference/hooks/use-node-connections) hook and then fetching the data for the first connected node with [`updateNodeData`](/api-reference/types/react-flow-instance#update-node-data).
Note that each handle can have multiple nodes connected to it and you might
want to restrict the number of connections to a single handle inside your
application. Check out the [connection limit
example](/examples/nodes/connection-limit) to see how to do that.
And there you go! Try changing the input values and see the color change
in real time.
### Improving the code
It might seem awkward to get the connections first, and then the data separately for each handle. For nodes with multiple handles like these, you should consider creating a custom handle component that isolates connection states and node data binding. We can create one inline.
```jsx filename="ColorPreview.js"
// {...}
function CustomHandle({ id, label, onChange }) {
const connections = useNodeConnections({
handleType: 'target',
handleId: id,
});
const nodeData = useNodesData(connections?.[0].source);
useEffect(() => {
onChange(nodeData?.data ? nodeData.data.value : 0);
}, [nodeData]);
return (
);
}
```
We can promote color to local state and declare each handle like this:
```jsx filename="ColorPreview.js"
// {...}
function ColorPreview() {
const [color, setColor] = useState({ r: 0, g: 0, b: 0 });
return (
setColor((c) => ({ ...c, r: value }))}
/>
setColor((c) => ({ ...c, g: value }))}
/>
setColor((c) => ({ ...c, b: value }))}
/>
);
}
export default ColorPreview;
```
## Getting more complex
Now we have a simple example of how to pipe data through React Flow. What if we want to do something more complex, like transforming the data along the way? Or even take different paths? We can do that too!
### Continuing the flow
Let's extend our flow. Start by adding an output `` to the color node and remove the local component state.
Because there are no inputs fields on this node, we don't need to keep a local
state at all. We can just read and update the node's `data` object directly.
Next, we add a new node (`Lightness.js`) that takes in a color object and determines if it is either a light or dark color. We can use the [relative luminance formula](https://en.wikipedia.org/wiki/Relative_luminance#Relative_luminance_and_%22gamma_encoded%22_colorspaces)
`luminance = 0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b`
to calculate the perceived brightness of a color (0 being the darkest and 255 being the brightest). We can assume everything >= 128 is a light color.
### Conditional branching
What if we would like to take a different path in our flow based on the perceived lightness? Let's give our lightness node two source handles `light` and `dark` and separate the node `data` object by source handle IDs. This is needed if you have multiple source handles to distinguish between each source handle's data.
But what does it mean to "take a different route"? One solution would be to assume that `null` or `undefined` data hooked up to a target handle is considered a "stop". In our case we can write the incoming color into `data.values.light` if it's a light color and into `data.values.dark` if it's a dark color and set the respective other value to `null`.
Don't forget to add `flex-direction: column;` and `align-items: end;` to reposition the handle labels.
Cool! Now we only need a last node to see if it actually works... We can create a custom debugging node (`Log.js`) that displays the hooked up data, and we're done!
## Summary
You have learned how to move data through the flow and transform it along the way.
All you need to do is
1. store data inside the node's `data` object with help of [`updateNodeData`](/api-reference/types/react-flow-instance#update-node-data) callback.
2. find out which nodes are connected by using [`useNodeConnections`](/api-reference/hooks/use-node-connections) and then use [`useNodesData`](/api-reference/hooks/use-nodes-data) for receiving the data from the connected nodes.
You can implement branching for example by interpreting incoming data that is undefined as a "stop". As a side note, most flow graphs that also have a branching usually separate the triggering of nodes from the actual data hooked up to the nodes. Unreal Engines Blueprints are a good example for this.
One last note before you go: you should find a consistent way of structuring
all your node data, instead of mixing ideas like we did just now. This means
for example, if you start working with splitting data by handle ID you should
do it for all nodes, regardless whether they have multiple handles or not.
Being able to make assumptions about the structure of your data throughout
your flow will make life a lot easier.
import { Callout } from 'nextra/components';
import { RemoteCodeViewer } from 'xy-shared/server';
# Devtools and Debugging
This is an ongoing experiment on implementing our own React Flow devtools. While we are
working on the actual package, we'd love to hear about your feedback and ideas on
[Discord](https://discord.gg/Bqt6xrs) or via mail at [info@xyflow.com](mailto:info@xyflow.com).
React Flow can often seem like a magic black box, but in reality you can reveal quite a
lot about its internal state if you know where to look. In this guide we will show you
three different ways to reveal the internal state of your flow:
* A `` component that shows the current position and zoom level of the
viewport.
* A `` component that reveals the state of each node.
* A `` that wraps your flow's `onNodesChange` handler and logs each change
as it is dispatched.
While we find these tools useful for making sure React Flow is working properly, you might
also find them useful for debugging your applications as your flows and their interactions
become more complex.
We encourage you to copy any or all of the components from this example into your own
projects and modify them to suit your needs: each component works independently!
## Node Inspector
The `` component makes use of our
[`useNodes`](/api-reference/hooks/use-nodes) hook to access all the nodes in the flow.
Typically we discourage using this hook because it will trigger a re-render any time *any*
of your nodes change, but that's exactly what makes it so useful for debugging!
The `width` and `height` properties are added to each node by React Flow after it has
measured the node's dimensions. We pass those dimensions, as well as other information
like the node's id and type, to a custom `` component.
We make use of the [``](/api-reference/components/viewport-portal)
component to let us render the inspector into React Flow's viewport. That means it's
content will be positioned and transformed along with the rest of the flow as the user
pans and zooms.
## Change Logger
Any change to your nodes and edges that originates from React Flow itself is communicated
to you through the `onNodesChange` and `onEdgesChange` callbacks. If you are working with
a controlled flow (that means you're managing the nodes and edges yourself), you need to
apply those changes to your state in order to keep everything in sync.
The `` component wraps your user-provided `onNodesChange` handler with a
custom function that intercepts and logs each change as it is dispatched. We can do this
by using the [`useStore`](/api-reference/hooks/use-store) and
[`useStoreApi`](/api-reference/hooks/use-store-api) hooks to access the store and and then
update React Flow's internal state accordingly. These two hooks give you powerful access
to React Flow's internal state and methods.
Beyond debugging, using the `` can be a great way to learn more about how
React Flow works and get you thinking about the different functionality you can build on
top of each change.
You can find documentation on the [`NodeChange`](/api-reference/types/node-change) and
[`EdgeChange`](/api-reference/types/edge-change) types in the API reference.
## Viewport Logger
The `` is the simplest example of what state you can pull out of React
Flow's store if you know what to look for. The state of the viewport is stored internally
under the `transform` key (a name we inherited from
[d3-zoom](https://d3js.org/d3-zoom#zoomTransform)). This component extracts the `x`, `y`,
and `zoom` components of the transform and renders them into a
[``](/api-reference/components/panel) component.
## Let us know what you think
As mentioned above, if you have any feedback or ideas on how to improve the devtools,
please let us know on [Discord](https://discord.gg/Bqt6xrs) or via mail at
[info@xyflow.com](mailto:info@xyflow.com). If you build your own devtools using these ideas, we'd love to hear about
it!
import { RemoteCodeViewer } from 'xy-shared/server';
# Hooks and Providers
React Flow provides several [hooks](/api-reference/hooks) and a context provider
for you to enhance the functionality of your flow. These tools help you to
manage state, access internal methods, and create custom components more
effectively.
## ReactFlowProvider
The ReactFlowProvider is a context provider that allows you to access the
internal state of the flow, such as nodes, edges, and viewport, from anywhere in
your component tree even outside the [`ReactFlow`](/api-reference/react-flow)
component. It is typically used at the top level of your application.
There are several cases where you might need to use the
[`ReactFlowProvider`](/api-reference/react-flow-provider) component:
* Many of the [hooks](/api-reference/hooks) we provide rely on this component to
work.
* You want to access the internal state of the flow outside of the `ReactFlow`
component.
* You are working with multiple flows on a page.
* You are using a client-side router.
## useReactFlow
The [`useReactFlow`](/api-reference/hooks/use-react-flow) hook provides access
to the [`ReactFlowInstance`](/api-reference/types/react-flow-instance) and its
methods. It allows you to manipulate nodes, edges, and the viewport
programmatically.
This example illustrates how to use the `useReactFlow` hook.
# Performance
When dealing with a large number of nodes or complex components, managing performance can
be challenging. Here are a few effective strategies to optimize the performance of React
Flow.
## Use memoization
One of the main reasons for performance issues in React Flow is unnecessary re-renders.
Since node movements trigger frequent state updates, this can lead to performance
bottlenecks, especially in larger diagrams.
### Memoize components
Components provided as props to the `` component, including custom node and
edge components, should either be memoized using `React.memo` or declared outside the
parent component. This ensures that React does not create a new reference for the
component on every render, which would otherwise trigger unnecessary re-renders.
```tsx
const NodeComponent = memo(() => {
return
{data.label}
;
});
```
### Memoize functions
Similarly, functions passed as props to `` should be memoized using
`useCallback`. This prevents React from creating a new function reference on every render,
which could also trigger unnecessary re-renders. Additionally, arrays and objects like
`defaultEdgeOptions` or `snapGrid` should be memoized using `useMemo` to prevent
unnecessary re-renders.
```tsx
import React, { useCallback } from 'react';
const MyDiagram = () => {
const onNodeClick = useCallback((event, node) => {
console.log('Node clicked:', node);
}, []);
return ;
};
export default MyDiagram;
```
## Avoid accessing nodes in components
One of the most common performance pitfalls in React Flow is directly accessing
the `nodes` or `edges` in the components or the viewport. These objects change frequently
during operations like dragging, panning, or zooming, which can cause unnecessary
re-renders of components that depend on them.
For example, if you fetch the entire `nodes` array from the store and filter it to display
selected node IDs, this approach can lead to performance degradation. Every update to
the `nodes` array triggers a re-render of all dependent components, even if the change is
unrelated to the selected nodes.
### Inefficient example
```tsx
const SelectedNodeIds = () => {
// ❌ This will cause unnecessary re-renders!
const nodes = useStore((state) => state.nodes);
const selectedNodeIds = nodes.filter((node) => node.selected).map((node) => node.id);
return (
{selectedNodeIds.map((id) => (
{id}
))}
);
};
```
In this example, every update to the `nodes` array causes the `SelectedNodeIds` component
to re-render, even if the selection hasn’t changed.
### Optimized solution
To avoid unnecessary re-renders, store the selected nodes in a separate field in your
state (using Zustand, Redux, or any other state management solution). This ensures that
the component only re-renders when the selection changes.
```tsx
const SelectedNodeIds = () => {
const selectedNodeIds = useStore((state) => state.selectedNodeIds);
return (
{selectedNodeIds.map((id) => (
{id}
))}
);
};
```
By decoupling the selected nodes from the `nodes` array, you prevent unnecessary updates
and improve performance. For more information, view our
[State Management guide](/learn/advanced-use/state-management).
## Collapse large node trees
If your node tree is deeply nested, rendering all nodes at once can be inefficient.
Instead, show only a limited number of nodes and allow users to expand them as needed. You
can do this by modifying the node’s `hidden` property dynamically to toggle visibility.
```tsx
const handleNodeClick = (targetNode) => {
if (targetNode.data.children) {
setNodes((prevNodes) =>
prevNodes.map((node) =>
targetNode.data.children.includes(node.id)
? { ...node, hidden: !node.hidden }
: node,
),
);
}
};
```
By hiding nodes initially and rendering them only when expanded, we optimize performance
while maintaining usability.
## Simplify node and edge styles
If you've optimized performance in every other way, and you are still finding performance
issues with large numbers of nodes, complex CSS styles, particularly those involving
animations, shadows, or gradients, can significantly impact performance. Consider reducing
complexity on your node styles in these cases.
## Additional resources
Here are a few helpful resources on performance in React Flow that you can check out:
* [Guide to Optimize React Flow Project Performance](https://www.synergycodes.com/blog/guide-to-optimize-react-flow-project-performance)
* [Tuning Edge Animations ReactFlow Optimal Performance](https://liambx.com/blog/tuning-edge-animations-reactflow-optimal-performance)
* [5 Ways to Optimize React Flow in 10 minutes](https://www.youtube.com/watch?v=8M2qZ69iM20)
# ======= Server Side Rendering =======
# Server side rendering, server side generation
import { Callout } from 'nextra/components';
Server side rendering is supported since React Flow 12
This is an advanced use case and assumes you are already familiar with React Flow. If you're new to React Flow, check out our [getting started guide](/learn/getting-started/installation-and-requirements).
In this guide you will learn how to configure React Flow to render a flow on the server, which will allow you to
* Display static HTML diagrams in documentation
* Render React Flow diagrams in non-js environments
* Dynamically generate open graph images that appear as embeds when sharing a link to your flow
(If you want to download an image of your flow, there's an easier way to do that on the client-side in our [download image example](/examples/misc/download-image).)
### Node dimensions
You need to configure a few things to make React Flow work on the server, the most important being the node dimensions. React Flow only renders nodes if they have a width and height. Usually you pass nodes without a specific `width` and `height`, they are then measured and the dimensions get written to `measured.width` and `measured.height`. Since we can't measure the dimensions on the server, we need to pass them explicitly. This can be done with the `width` and `height` or the `initialWidth` and `initialHeight` node properties.
```js
const nodes = [
{
id: '1',
type: 'default',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
width: 100,
height: 50,
},
];
```
React Flow now knows the dimensions of the node and can render it on the server. The `width` and `height` properties are used as an inline style for the node. If you expect nodes to have different dimensions on the client or if the dimensions should by dynamic based on the content, you can use the `initialWidth` and `initialHeight` properties. They are only used for the first render (on the server or on the client) as long as the nodes are not measured and `measured.width` and `measured.height` are not set.
There are two ways to specify node dimensions for server side rendering:
1. `width` and `height` for static dimensions that are known in advance and don't
change.
2. `initialWidth` and `initialHeight` for dynamic dimensions that are not known in
advance or change.
### Handle positions
You probably also want to render the edges on the server. On the client, React Flow checks the positions of the handles and stores that information to draw the edges. Since we can't measure the handle positions on the server, we need to pass this information, too. This can be done with the `handles` property of a node.
```js
const nodes: Node[] = [
{
id: '1',
type: 'default',
position: { x: 0, y: 0 },
data: { label: 'Node 1' },
width: 100,
height: 50,
handles: [
{
type: 'target',
position: Position.Top,
x: 100 / 2,
y: 0,
},
{
type: 'source',
position: Position.Bottom,
x: 100 / 2,
y: 50,
},
],
},
];
```
With this additional information, React Flow knows enough about the handles to render the edges on the server. If you are fine with just rendering the nodes, you can skip this step.
### Using `fitView` on the server
If you know the dimensions of the React Flow container itself, you can even use `fitView` on the server. For this, you need to pass the `width` and `height` of the container to the `ReactFlow` component.
```js
```
This will calculate the viewport and set the `transform` on the server in order to include all nodes in the viewport.
### Usage with the ``
If you are using the `ReactFlowProvider`, you can pass `initialNodes`, `initialEdges` and optional wrapper dimensions (`initialWidth` and `initialHeight`) and `fitView` to the provider.
```js
```
The `initial-` prefix means that these values are only used for the first render. After that, the provider will use the `nodes` and `edges` from the context.
### Creating static HTML
If you want to create static HTML, you can use the `renderToStaticMarkup` function from React. This will render the React Flow component to a string of HTML. You can then use this string to create a static HTML file or send it as a response to an HTTP request.
```js
import React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { ReactFlow, Background } from '@xyflow/react';
function toHTML({ nodes, edges, width, height }) {
const html = renderToStaticMarkup(
React.createElement(
ReactFlow,
{
nodes,
edges,
width,
height,
minZoom: 0.2,
fitView: true,
},
React.createElement(Background, null),
),
);
return html;
}
```
# Using a State Management Library
import { Callout } from 'nextra/components';
import { RemoteCodeViewer } from 'xy-shared/server';
For this guide we assume that you already know about the [core
concepts](/learn/concepts/core-concepts) of React Flow and how to implement
[custom nodes](/learn/customization/custom-nodes). You should also be familiar
with the concepts of state management libraries and how to use them.
In this guide, we explain how to use React Flow with the state management library [Zustand](https://github.com/pmndrs/zustand). We will build a small app where each node features a color chooser that updates its background color. We chose Zustand for this guide because React Flow already uses it internally, but you can easily use other state management libraries such as [Redux](https://redux.js.org/), [Recoil](https://recoiljs.org/) or [Jotai](https://jotai.org/)
As demonstrated in previous guides and examples, React Flow can easily be used with a local component state to manage nodes and edges in your diagram. However, as your application grows and you need to update the state from within individual nodes, managing this state can become more complex. Instead of passing functions through the node's data field, you can use a [React context](https://reactjs.org/docs/context.html) or integrate a state management library like Zustand, as outlined in this guide.
## Install Zustand
As mentioned above we are using Zustand in this example. Zustand is a bit like Redux: you have a central store with actions to alter your state and hooks to access your state. You can install Zustand via:
```bash copy npm2yarn
npm install --save zustand
```
## Create a store
Zustand lets you create a hook for accessing the values and functions of your store. We put the `nodes` and `edges` and the `onNodesChange`, `onEdgesChange`, `onConnect`, `setNodes` and `setEdges` functions in the store to get the basic interactivity for our graph:
That's the basic setup. We now have a store with nodes and edges that can handle the changes (dragging, selecting or removing a node or edge) triggered by React Flow. When you take a look at the `App.tsx` file, you can see that it's kept nice and clean. All the data and actions are now part of the store and can be accessed with the `useStore` hook.
## Implement a color change action
We add a new `updateNodeColor` action to update the `data.color` field of a specific node. For this we pass the node id and the new color to the action, iterate over the nodes and update the matching one with the new color:
```ts
updateNodeColor: (nodeId: string, color: string) => {
set({
nodes: get().nodes.map((node) => {
if (node.id === nodeId) {
// it's important to create a new object here, to inform React Flow about the changes
return { ...node, data: { ...node.data, color } };
}
return node;
}),
});
};
```
This new action can now be used in a React component like this:
```tsx
const updateNodeColor = useStore((s) => s.updateNodeColor);
...