react-flow-usage
SKILL.md
React Flow Usage Guide
Comprehensive patterns and best practices for building production-ready node-based UIs with React Flow (@xyflow/react v12+).
When to Use This Skill
Apply these guidelines when:
- Building workflow editors, flow diagrams, or node-based interfaces
- Creating custom node or edge components
- Implementing drag-and-drop functionality for visual programming
- Optimizing performance for graphs with 100+ nodes
- Managing flow state, save/restore, or undo/redo
- Implementing auto-layout with dagre, elkjs, or custom algorithms
- Integrating React Flow with TypeScript
Rule Categories by Priority
| Priority | Category | Focus | Prefix |
|---|---|---|---|
| 1 | Setup & Configuration | CRITICAL | setup- |
| 2 | Performance Optimization | CRITICAL | perf- |
| 3 | Node Patterns | HIGH | node- |
| 4 | Edge Patterns | HIGH | edge- |
| 5 | State Management | HIGH | state- |
| 6 | Hooks Usage | MEDIUM | hook- |
| 7 | Layout & Positioning | MEDIUM | layout- |
| 8 | Interaction Patterns | MEDIUM | interaction- |
| 9 | TypeScript Integration | MEDIUM | typescript- |
Quick Start Pattern
import { useCallback } from 'react';
import {
ReactFlow,
Background,
Controls,
MiniMap,
useNodesState,
useEdgesState,
addEdge
} from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const initialNodes = [
{ id: '1', position: { x: 0, y: 0 }, data: { label: 'Node 1' } },
];
const initialEdges = [
{ id: 'e1-2', source: '1', target: '2' },
];
// Define outside component or use useMemo
const nodeTypes = { custom: CustomNode };
const edgeTypes = { custom: CustomEdge };
function Flow() {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = useCallback(
(params) => setEdges((eds) => addEdge(params, eds)),
[setEdges]
);
return (
<div style={{ width: '100%', height: '100vh' }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
fitView
>
<Background />
<Controls />
<MiniMap />
</ReactFlow>
</div>
);
}
Core Concepts Overview
Node Structure
id: Unique identifier (required)position:{ x: number, y: number }(required)data: Custom data object (required)type: Built-in or custom typestyle,className: Stylingdraggable,selectable,connectable: Interaction controlsparentId: For nested/grouped nodesextent: Movement boundaries
Edge Structure
id: Unique identifier (required)source: Source node id (required)target: Target node id (required)sourceHandle,targetHandle: Specific handle idstype: 'default' | 'straight' | 'step' | 'smoothstep' | customanimated: Boolean for animationlabel: String or React componentmarkerStart,markerEnd: Arrow markers
Handle Usage
- Position:
Position.Top | Bottom | Left | Right - Type:
'source' | 'target' - Multiple handles per node supported
- Use unique
idprop for multiple handles
Essential Patterns
Custom Nodes
import { memo } from 'react';
import { Handle, Position, NodeProps } from '@xyflow/react';
const CustomNode = memo(({ data, selected }: NodeProps) => {
return (
<div className={`custom-node ${selected ? 'selected' : ''}`}>
<Handle type="target" position={Position.Top} />
<div>{data.label}</div>
<Handle type="source" position={Position.Bottom} />
</div>
);
});
// IMPORTANT: Define outside component
const nodeTypes = { custom: CustomNode };
Custom Edges
import { BaseEdge, EdgeLabelRenderer, getBezierPath, EdgeProps } from '@xyflow/react';
function CustomEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition }: EdgeProps) {
const [edgePath, labelX, labelY] = getBezierPath({
sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition,
});
return (
<>
<BaseEdge path={edgePath} />
<EdgeLabelRenderer>
<div style={{
position: 'absolute',
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
}}>
Custom Label
</div>
</EdgeLabelRenderer>
</>
);
}
Performance Optimization
// 1. Memoize node/edge types (define outside component)
const nodeTypes = useMemo(() => ({ custom: CustomNode }), []);
// 2. Memoize callbacks
const onConnect = useCallback((params) =>
setEdges((eds) => addEdge(params, eds)), [setEdges]
);
// 3. Use simple edge types for large graphs
const edgeType = nodes.length > 100 ? 'straight' : 'smoothstep';
// 4. Avoid unnecessary re-renders in custom components
const CustomNode = memo(({ data }) => <div>{data.label}</div>);
Key Hooks
useReactFlow()- Access flow instance methods (getNodes, setNodes, fitView, etc.)useNodesState()/useEdgesState()- Managed state with change handlersuseNodes()/useEdges()- Reactive access to current nodes/edgesuseNodesData(id)- Get specific node data (more performant than useNodes)useHandleConnections()- Get connections for a handleuseConnection()- Track connection in progressuseStore()- Direct store access (use sparingly)
Common Patterns
Drag and Drop
const onDrop = useCallback((event) => {
event.preventDefault();
const type = event.dataTransfer.getData('application/reactflow');
const position = screenToFlowPosition({
x: event.clientX,
y: event.clientY,
});
setNodes((nds) => nds.concat({
id: getId(),
type,
position,
data: { label: `${type} node` },
}));
}, [screenToFlowPosition]);
Save and Restore
const { toObject } = useReactFlow();
// Save
const flow = toObject();
localStorage.setItem('flow', JSON.stringify(flow));
// Restore
const flow = JSON.parse(localStorage.getItem('flow'));
setNodes(flow.nodes || []);
setEdges(flow.edges || []);
setViewport(flow.viewport);
Connection Validation
const isValidConnection = useCallback((connection) => {
// Prevent self-connections
if (connection.source === connection.target) return false;
// Custom validation logic
return true;
}, []);
Detailed Rules
For comprehensive patterns and best practices, see individual rule files in the rules/ directory organized by category:
rules/setup-*.md - Critical setup patterns
rules/perf-*.md - Performance optimization
rules/node-*.md - Node customization patterns
rules/edge-*.md - Edge handling patterns
rules/state-*.md - State management
rules/hook-*.md - Hooks usage
rules/layout-*.md - Layout and positioning
rules/interaction-*.md - User interactions
rules/typescript-*.md - TypeScript integration
Full Compiled Documentation
For the complete guide with all rules and examples expanded: see AGENTS.md
Scraped Documentation Reference
Comprehensive scraped documentation from reactflow.dev is available in scraped/:
- Learn:
scraped/learn-concepts/,scraped/learn-customization/,scraped/learn-advanced/ - API:
scraped/api-hooks/,scraped/api-types/,scraped/api-utils/,scraped/api-components/ - Examples:
scraped/examples-nodes/,scraped/examples-edges/,scraped/examples-interaction/,scraped/examples-layout/ - UI Components:
scraped/ui-components/ - Tutorials:
scraped/learn-tutorials/ - Troubleshooting:
scraped/learn-troubleshooting/
Common Issues
- Couldn't create edge - Add
onConnecthandler - Nodes not draggable - Check
nodesDraggableprop - CSS not loading - Import
@xyflow/react/dist/style.css - useReactFlow outside provider - Wrap with
<ReactFlowProvider> - Performance issues - See Performance category rules
- TypeScript errors - Use proper generic types
useReactFlow<NodeType, EdgeType>()
References
- Official Documentation: https://reactflow.dev
- GitHub: https://github.com/xyflow/xyflow
- Package:
@xyflow/react(npm) - Examples: https://reactflow.dev/examples
- API Reference: https://reactflow.dev/api-reference
Weekly Installs
20
Repository
thedogwiththeda…act-flowGitHub Stars
2
First Seen
Jan 23, 2026
Security Audits
Installed on
codex15
opencode14
claude-code13
cursor12
gemini-cli11
github-copilot10