CtrlK
BlogDocsLog inGet started
Tessl Logo

gedsys/react-flow-usage

Comprehensive React Flow (@xyflow/react) patterns and best practices for building node-based UIs, workflow editors, and interactive diagrams. Use when working with React Flow for (1) building flow editors or node-based interfaces, (2) creating custom nodes and edges, (3) implementing drag-and-drop workflows, (4) optimizing performance for large graphs, (5) managing flow state and interactions, (6) implementing auto-layout or positioning, or (7) TypeScript integration with React Flow.

95

Quality

95%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

SKILL.md

name:
react-flow-usage
description:
Comprehensive React Flow (@xyflow/react) patterns and best practices for building node-based UIs, workflow editors, and interactive diagrams. Use when working with React Flow for (1) building flow editors or node-based interfaces, (2) creating custom nodes and edges, (3) implementing drag-and-drop workflows, (4) optimizing performance for large graphs, (5) managing flow state and interactions, (6) implementing auto-layout or positioning, or (7) TypeScript integration with React Flow.
license:
MIT
metadata:
{"author":"xyflow Team","version":"1.0.0","package":"@xyflow/react"}

React Flow Usage Guide

Comprehensive patterns and best practices for building production-ready node-based UIs with React Flow (@xyflow/react v12+).

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

Essential Patterns

Custom Nodes

import { memo } from 'react';
import { Handle, Position, NodeProps } from '@xyflow/react';

// Node props: id, position: { x, y }, data, type, parentId, extent, draggable/selectable/connectable
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';

// Edge props: id, source, target, sourceHandle/targetHandle, type ('default' | 'straight' | 'step' | 'smoothstep'), animated, label, markerStart/markerEnd
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 handlers
  • useNodes() / useEdges() - Reactive access to current nodes/edges
  • useNodesData(id) - Get specific node data (more performant than useNodes)
  • useHandleConnections() - Get connections for a handle
  • useConnection() - Track connection in progress
  • useStore() - Direct store access (use sparingly)

Common Patterns

Drag and Drop

const onDrop = useCallback((event) => {
  event.preventDefault();
  const type = event.dataTransfer.getData('application/reactflow');

  // Validate that a recognized type was dragged
  if (!type) return;

  const position = screenToFlowPosition({
    x: event.clientX,
    y: event.clientY,
  });

  const newNode = {
    id: getId(),
    type,
    position,
    data: { label: `${type} node` },
  };

  setNodes((nds) => {
    const updated = nds.concat(newNode);
    // Verify node was added; log a warning if the id already existed
    if (updated.length === nds.length) {
      console.warn(`Node with id ${newNode.id} already exists — skipping.`);
    }
    return updated;
  });
}, [screenToFlowPosition]);

// Also wire up onDragOver to enable drop
const onDragOver = useCallback((event) => {
  event.preventDefault();
  event.dataTransfer.dropEffect = 'move';
}, []);

Save and Restore

const { toObject } = useReactFlow();

// Save
const saveFlow = () => {
  try {
    const flow = toObject();
    localStorage.setItem('flow', JSON.stringify(flow));
  } catch (err) {
    console.error('Failed to save flow:', err);
  }
};

// Restore
const restoreFlow = () => {
  try {
    const raw = localStorage.getItem('flow');
    if (!raw) return;
    const flow = JSON.parse(raw);
    // Validate expected structure before applying
    if (!Array.isArray(flow.nodes) || !Array.isArray(flow.edges)) return;
    setNodes(flow.nodes);
    setEdges(flow.edges);
    if (flow.viewport) setViewport(flow.viewport);
    // Verify restored flow renders correctly: call fitView after state updates settle
    setTimeout(() => fitView(), 0);
  } catch (err) {
    console.error('Failed to restore flow:', err);
    // On error, reset to a known-good empty state
    setNodes([]);
    setEdges([]);
  }
};

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

  1. Couldn't create edge - Add onConnect handler
  2. Nodes not draggable - Check nodesDraggable prop
  3. CSS not loading - Import @xyflow/react/dist/style.css
  4. useReactFlow outside provider - Wrap with <ReactFlowProvider>
  5. Performance issues - See Performance category rules
  6. 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

ALL_LINKS.md

README.md

SKILL.md

tile.json