react-flow-implementation

React Flow Implementation

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "react-flow-implementation" with this command: npx skills add existential-birds/beagle/existential-birds-beagle-react-flow-implementation

React Flow Implementation

Quick Start

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> ); }

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.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

tailwind-v4

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-flow

No summary provided by upstream source.

Repository SourceNeeds Review
General

react-router-v7

No summary provided by upstream source.

Repository SourceNeeds Review
General

vitest-testing

No summary provided by upstream source.

Repository SourceNeeds Review