
React Flow Implementation
- 316 installs
- 74 repo stars
- Updated July 21, 2026
- existential-birds/beagle
react-flow-implementation is a frontend implementation skill that builds node-based editors with @xyflow/react for developers who need correct nodes, edges, handles, styles, and state wiring in React.
About
react-flow-implementation is a frontend implementation skill for building node-based UIs with @xyflow/react (React Flow). react-flow-implementation focuses on the wiring that commonly breaks in flow editors: nodes and edges state, add-edge callbacks, custom node components with handles, and including the required React Flow stylesheet import. react-flow-implementation is useful when a developer is implementing a visual editor, diagram builder, or workflow canvas and needs predictable viewport behavior and consistent state updates. Developers reach for react-flow-implementation when they want a working baseline quickly and then iterate into custom nodes, interactions, and persisted graph state without missing key integration steps.
- Quick-start pattern with useNodesState, useEdgesState, addEdge, and mandatory @xyflow/react CSS import
- Ordered implementation gates: styles, container sizing, handles, custom nodes, and state before shipping polish
- Covers nodes, edges, handles, custom components, state management, and viewport control
- Explicit trigger: flow charts, diagrams, visual editors, and node-based applications
React Flow Implementation by the numbers
- 316 all-time installs (skills.sh)
- Ranked #738 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/existential-birds/beagle --skill react-flow-implementationAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 316 |
|---|---|
| repo stars | ★ 74 |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 21, 2026 |
| Repository | existential-birds/beagle ↗ |
How do I implement React Flow with custom nodes?
Implement node-based flow charts, diagrams, and visual editors with @xyflow/react without missing styles, handles, or state wiring.
Who is it for?
Frontend developers building diagrams, workflow canvases, or visual editors in React.
Skip if: Backend-only projects without a React UI surface.
When should I use this skill?
Invoke when a developer is building a node graph UI with @xyflow/react and needs correct state, handles, or styling.
What you get
A working React Flow screen with nodes, edges, state hooks, edge-creation handler, and required stylesheet import.
- react flow screen
- custom node scaffolding
- node/edge state wiring
By the numbers
- Example setup initializes 2 nodes in `initialNodes`.
Files
React Flow Implementation
Quick Start
import { useCallback } from 'react';
import { ReactFlow, 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' } },
{ id: '2', position: { x: 200, y: 100 }, data: { label: 'Node 2' } },
];
const initialEdges = [{ id: 'e1-2', source: '1', target: '2' }];
export default function Flow() {
const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);
const onConnect = useCallback(
(connection) => setEdges((eds) => addEdge(connection, eds)),
[setEdges]
);
return (
<div style={{ width: '100%', height: '100vh' }}>
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
onConnect={onConnect}
fitView
/>
</div>
);
}Implementation gates
Run these in order; do not skip ahead on “looks fine.”
1. Styles on the page — Pass if the bundle that renders <ReactFlow /> imports @xyflow/react/dist/style.css (or equivalent CSS pipeline) so nodes/edges are visible and hit-targets match visuals. 2. `useReactFlow` boundary — Pass if every caller of useReactFlow() is a descendant of <ReactFlowProvider> that wraps the same tree as <ReactFlow /> (or you have intentionally split stores and can name both roots). 3. Stable `nodeTypes` / `edgeTypes` — Pass if those maps are module-scope constants or useMemo with stable deps—not a new { ... } literal each render in the component that renders <ReactFlow />. 4. Handles match edges — Pass if for nodes with multiple Handle ids, every edge that must land on a specific handle sets sourceHandle / targetHandle accordingly (or you accept default handle resolution deliberately).
See ADDITIONAL_COMPONENTS.md for MiniMap, Controls, Background, NodeToolbar, and NodeResizer patterns.
Core Patterns
TypeScript Types
import type { Node, Edge, NodeProps, BuiltInNode } from '@xyflow/react';
// Define custom node type with data shape
type CustomNode = Node<{ value: number; label: string }, 'custom'>;
// Combine with built-in nodes
type MyNode = CustomNode | BuiltInNode;
type MyEdge = Edge<{ weight?: number }>;
// Use throughout app
const [nodes, setNodes] = useNodesState<MyNode>(initialNodes);Custom Nodes
import { memo } from 'react';
import { Handle, Position, type NodeProps } from '@xyflow/react';
// Define node type
type CounterNode = Node<{ count: number }, 'counter'>;
// Always wrap in memo for performance
const CounterNode = memo(function CounterNode({ data, isConnectable }: NodeProps<CounterNode>) {
return (
<>
<Handle type="target" position={Position.Top} isConnectable={isConnectable} />
<div className="counter-node">
Count: {data.count}
{/* nodrag prevents dragging when interacting with button */}
<button className="nodrag" onClick={() => console.log('clicked')}>
Increment
</button>
</div>
<Handle type="source" position={Position.Bottom} isConnectable={isConnectable} />
</>
);
});
// Register in nodeTypes (define OUTSIDE component to avoid re-renders)
const nodeTypes = { counter: CounterNode };
// Use in ReactFlow
<ReactFlow nodeTypes={nodeTypes} ... />Multiple Handles
// Use handle IDs when a node has multiple handles of same type
<Handle type="source" position={Position.Right} id="a" />
<Handle type="source" position={Position.Right} id="b" style={{ top: 20 }} />
// Connect with specific handles
const edge = {
id: 'e1-2',
source: '1',
sourceHandle: 'a',
target: '2',
targetHandle: null
};Custom Edges
import { BaseEdge, EdgeProps, getSmoothStepPath } from '@xyflow/react';
function CustomEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data }: EdgeProps) {
const [edgePath, labelX, labelY] = getSmoothStepPath({
sourceX, sourceY, sourcePosition,
targetX, targetY, targetPosition,
});
return (
<>
<BaseEdge id={id} path={edgePath} />
<text x={labelX} y={labelY} className="edge-label">{data?.label}</text>
</>
);
}
const edgeTypes = { custom: CustomEdge };State Management
Controlled (Recommended for Production)
// External state with change handlers
const [nodes, setNodes] = useState<Node[]>(initialNodes);
const [edges, setEdges] = useState<Edge[]>(initialEdges);
const onNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[]
);
const onEdgesChange = useCallback(
(changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
[]
);
<ReactFlow
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
/>Using useReactFlow
import { useReactFlow, ReactFlowProvider } from '@xyflow/react';
function FlowControls() {
const {
getNodes, setNodes, addNodes, updateNodeData,
getEdges, setEdges, addEdges,
fitView, zoomIn, zoomOut, setViewport,
deleteElements, toObject,
} = useReactFlow();
const addNode = () => {
addNodes({ id: `${Date.now()}`, position: { x: 100, y: 100 }, data: { label: 'New' } });
};
return <button onClick={addNode}>Add Node</button>;
}
// Must wrap in provider when using useReactFlow
function App() {
return (
<ReactFlowProvider>
<Flow />
<FlowControls />
</ReactFlowProvider>
);
}Updating Node Data
const { updateNodeData } = useReactFlow();
// Merge with existing data
updateNodeData(nodeId, { label: 'Updated' });
// Replace data entirely
updateNodeData(nodeId, { newField: 'value' }, { replace: true });Viewport & Fit View
// Fit on initial render
<ReactFlow fitView fitViewOptions={{ padding: 0.2, maxZoom: 1 }} />
// Programmatic control
const { fitView, setViewport, getViewport, zoomTo } = useReactFlow();
// Fit to specific nodes
fitView({ nodes: [{ id: '1' }, { id: '2' }], duration: 500 });
// Set exact viewport
setViewport({ x: 100, y: 100, zoom: 1.5 }, { duration: 300 });Connection Validation
const isValidConnection = useCallback((connection: Connection) => {
// Prevent self-connections
if (connection.source === connection.target) return false;
// Custom validation logic
const sourceNode = getNode(connection.source);
const targetNode = getNode(connection.target);
return sourceNode?.type !== targetNode?.type;
}, []);
<ReactFlow isValidConnection={isValidConnection} />Common Props Reference
<ReactFlow
// Core data
nodes={nodes}
edges={edges}
onNodesChange={onNodesChange}
onEdgesChange={onEdgesChange}
// Custom types (define OUTSIDE component)
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
// Connections
onConnect={onConnect}
connectionMode={ConnectionMode.Loose} // Allow target-to-target
isValidConnection={isValidConnection}
// Viewport
fitView
minZoom={0.1}
maxZoom={4}
defaultViewport={{ x: 0, y: 0, zoom: 1 }}
// Interaction
nodesDraggable={true}
nodesConnectable={true}
elementsSelectable={true}
panOnDrag={true}
zoomOnScroll={true}
// Additional components
<MiniMap />
<Controls />
<Background variant={BackgroundVariant.Dots} />
</ReactFlow>CSS Classes for Interaction
| Class | Effect |
|---|---|
nodrag | Prevent dragging when clicking element |
nowheel | Prevent zoom on wheel events |
nopan | Prevent panning from element |
nokey | Prevent keyboard events (use on inputs) |
Additional Components
See ADDITIONAL_COMPONENTS.md for MiniMap, Controls, Background, NodeToolbar, NodeResizer.
React Flow Additional Components
MiniMap
import { MiniMap } from '@xyflow/react';
<MiniMap
nodeColor={(node) => {
switch (node.type) {
case 'input': return '#6ede87';
case 'output': return '#ff0072';
default: return '#eee';
}
}}
nodeStrokeWidth={3}
zoomable
pannable
/>Controls
import { Controls } from '@xyflow/react';
<Controls
showZoom={true}
showFitView={true}
showInteractive={true}
position="bottom-left"
/>Background
import { Background, BackgroundVariant } from '@xyflow/react';
// Dots pattern
<Background variant={BackgroundVariant.Dots} gap={16} size={1} />
// Lines pattern
<Background variant={BackgroundVariant.Lines} gap={24} />
// Cross pattern
<Background variant={BackgroundVariant.Cross} />
// Custom color
<Background bgColor="#1a1a1a" color="#444" />NodeToolbar
import { NodeToolbar, Position } from '@xyflow/react';
function CustomNode({ id, selected }: NodeProps) {
return (
<>
<NodeToolbar
isVisible={selected}
position={Position.Top}
>
<button onClick={() => console.log('delete', id)}>Delete</button>
<button>Edit</button>
</NodeToolbar>
<div>Node Content</div>
</>
);
}NodeResizer
import { NodeResizer } from '@xyflow/react';
function ResizableNode({ selected }: NodeProps) {
return (
<>
<NodeResizer
isVisible={selected}
minWidth={100}
minHeight={50}
handleStyle={{ width: 8, height: 8 }}
/>
<div style={{ padding: 10 }}>
Resize me
</div>
</>
);
}EdgeToolbar (for custom edges)
import { EdgeToolbar } from '@xyflow/react';
function CustomEdge({ id, selected, ...props }: EdgeProps) {
const [path, labelX, labelY] = getSmoothStepPath(props);
return (
<>
<BaseEdge path={path} />
<EdgeToolbar x={labelX} y={labelY} isVisible={selected}>
<button>Edit</button>
</EdgeToolbar>
</>
);
}Panel
import { Panel } from '@xyflow/react';
// Positions: top-left, top-center, top-right, bottom-left, bottom-center, bottom-right
<ReactFlow ...>
<Panel position="top-right">
<button onClick={onSave}>Save</button>
<button onClick={onRestore}>Restore</button>
</Panel>
</ReactFlow>Edge Path Utilities
React Flow provides utilities for generating SVG paths for custom edges.
Available Path Functions
getBezierPath (Default)
import { getBezierPath, Position } from '@xyflow/react';
const [path, labelX, labelY, offsetX, offsetY] = getBezierPath({
sourceX: 0,
sourceY: 0,
sourcePosition: Position.Right,
targetX: 200,
targetY: 100,
targetPosition: Position.Left,
curvature: 0.25, // optional, default 0.25
});getSmoothStepPath
import { getSmoothStepPath } from '@xyflow/react';
const [path, labelX, labelY] = getSmoothStepPath({
sourceX, sourceY, sourcePosition,
targetX, targetY, targetPosition,
borderRadius: 5, // Corner rounding
offset: 20, // Distance from handle before first bend
stepPosition: 0.5, // 0-1, where bend occurs (0=source, 1=target)
});getStraightPath
import { getStraightPath } from '@xyflow/react';
const [path, labelX, labelY] = getStraightPath({
sourceX, sourceY,
targetX, targetY,
});getSimpleBezierPath
import { getSimpleBezierPath } from '@xyflow/react';
const [path, labelX, labelY] = getSimpleBezierPath({
sourceX, sourceY, sourcePosition,
targetX, targetY, targetPosition,
});Custom Edge Example
import { BaseEdge, EdgeProps, getSmoothStepPath, EdgeLabelRenderer } from '@xyflow/react';
function CustomEdge({
id, sourceX, sourceY, targetX, targetY,
sourcePosition, targetPosition, data, style
}: EdgeProps) {
const [edgePath, labelX, labelY] = getSmoothStepPath({
sourceX, sourceY, sourcePosition,
targetX, targetY, targetPosition,
});
return (
<>
<BaseEdge id={id} path={edgePath} style={style} />
<EdgeLabelRenderer>
<div
style={{
position: 'absolute',
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
pointerEvents: 'all',
}}
className="nodrag nopan"
>
<button onClick={() => console.log('edge clicked', id)}>
{data?.label}
</button>
</div>
</EdgeLabelRenderer>
</>
);
}Edge Markers
// Built-in markers
const edge = {
id: 'e1-2',
source: '1',
target: '2',
markerEnd: MarkerType.ArrowClosed,
// or custom:
markerEnd: {
type: MarkerType.Arrow,
color: '#f00',
width: 20,
height: 20,
},
};Related skills
How it compares
Pick this when you need a working @xyflow/react implementation with correct state hooks and styles, not just a diagram mock.
FAQ
Why is my React Flow canvas unstyled?
react-flow-implementation includes the required stylesheet import for @xyflow/react. react-flow-implementation uses `import '@xyflow/react/dist/style.css';` to ensure nodes, edges, and handles render with the library’s base styles.
How do I manage nodes and edges state cleanly?
react-flow-implementation uses React Flow’s state hooks to keep updates predictable. react-flow-implementation relies on `useNodesState` and `useEdgesState` so drag, connect, and custom update handlers can mutate graph state without manual reducers.
Is React Flow Implementation safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.