К основному содержанию
скилл CX Codex

react-flow-implementation — скилл для Claude Code: обзор и установка

Направляет агента при создании диаграмм и визуальных редакторов на базе @xyflow/react. Помогает избежать типичных ошибок с рендером узлов и связей.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add existential-birds/beagle --skill react-flow-implementation -a claude-code
Открыть на GitHub

Что делает react-flow-implementation

Скилл задаёт правила построения интерфейсов с библиотекой @xyflow/react. Он инструктирует модель правильно настраивать типизированные узлы (Node) и соединения (Edge), а также управлять полотном через хук useReactFlow.

Архитектура строится вокруг обязательных проверок. Без прямого импорта стилей @xyflow/react/dist/style.css узлы и хэндлы отобразятся с ошибками геометрии. Карты nodeTypes и edgeTypes скилл требует выносить за пределы компонентов, чтобы избежать постоянных перерисовок при каждом рендере. В кастомных узлах интерактивные элементы получают класс nodrag, который защищает клики от перехвата перетаскиванием.

Какие задачи решает

  • настроить кастомные узлы и связи в @xyflow/react с типами TypeScript
  • предотвратить лишние ререндеры полотна из-за нестабильных объектов nodeTypes
  • реализовать управление полотном и зумом через useReactFlow и ReactFlowProvider
  • настроить валидацию соединений и привязку связей к конкретным Handle

Примеры запросов агенту

  • Сделай визуальный редактор графов на @xyflow/react с кастомным узлом счётчика
  • Добавь на полотно React Flow валидацию связей, чтобы нельзя было соединить узел сам с собой
  • Настрой центрирование экрана через fitView и внешние кнопки зума с помощью useReactFlow

Как установить react-flow-implementation

1Через Skills CLI (Vercel)

npx skills add existential-birds/beagle --skill react-flow-implementation -a claude-code

2Вручную: положить файлы

~/.claude/skills/react-flow-implementation/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/react-flow-implementation/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о react-flow-implementation

Как установить react-flow-implementation в Claude Code?

Выполните команду npx skills add existential-birds/beagle --skill react-flow-implementation -a claude-code. Также можно поместить файл скилла вручную в ~/.claude/skills/react-flow-implementation/SKILL.md.

Зачем нужен этот скилл?

Он задаёт модели чёткие архитектурные ограничения при работе с @xyflow/react. Это исключает поломку стилей, циклические ререндеры и рассинхронизацию хэндлов с рёбрами.

Почему скилл требует выносить nodeTypes за пределы компонента?

Если объявлять объект nodeTypes внутри компонента без мемоизации, React Flow пересоздаёт реестр типов на каждом рендере. Скилл заставляет использовать константы на уровне модуля или useMemo.

Исходный текст

SKILL.md · Apache-2.0
---
name: react-flow-implementation
description: Implements React Flow node-based UIs correctly using @xyflow/react. Use when building flow charts, diagrams, visual editors, or node-based applications with React. Covers nodes, edges, handles, custom components, state management, and viewport control.
---

# React Flow Implementation

## Quick Start

```tsx
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` `id`s, every edge that must land on a specific handle sets `sourceHandle` / `targetHandle` accordingly (or you accept default handle resolution deliberately).

See [ADDITIONAL_COMPONENTS.md](ADDITIONAL_COMPONENTS.md) for MiniMap, Controls, Background, NodeToolbar, and NodeResizer patterns.

## Core Patterns

### TypeScript Types

```typescript
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

```tsx
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

```tsx
// 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

```tsx
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)

```tsx
// 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

```tsx
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

```tsx
const { updateNodeData } = useReactFlow();

// Merge with existing data
updateNodeData(nodeId, { label: 'Updated' });

// Replace data entirely
updateNodeData(nodeId, { newField: 'value' }, { replace: true });
```

## Viewport & Fit View

```tsx
// 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

```tsx
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

```tsx
<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](ADDITIONAL_COMPONENTS.md) for MiniMap, Controls, Background, NodeToolbar, NodeResizer.

© existential-birds · Apache-2.0 · existential-birds/beagle

Похожие скиллы

Всё по теме «Фронтенд и UI» →
frontend-design официальный anthropics Скилл задаёт осмысленное визуальное направление для новых интерфейсов и редизайна. Подойдёт, когда стандартный шаблонный UI не устраивает. 1 025 790установок design-taste-frontend Leonxlnx Скилл задаёт арт-дирекцию для публичных страниц и рабочих экранов, а затем проверяет результат в браузере по скриншотам. Нужен, когда интерфейс выглядит шаблонным или недоработанным. CX Codex +1 678 700установок prototype Matt Pocock Создаёт временный прототип, чтобы проверить логику, модель состояния или вид интерфейса до работы над основным кодом. 986 201установок hyperframes heygen-com Скилл задаёт агенту правила рендера HTML-кода в видео через HyperFrames. Помогает собирать проморолики, эксплейнеры и титры прямо в коде проекта. CX Codex +1 1 200 000установок hyperframes-cli heygen-com Управляет проектами HyperFrames через терминал: собирает таймлайн, проверяет контраст кадров, запускает предпросмотр и рендерит видео локально или в облаке. CX Codex +1 1 300 000установок webapp-testing официальный anthropics Скилл запускает проверки локальных веб-приложений через Playwright: помогает отлаживать UI, делать скриншоты и смотреть логи браузера. 186 758установок

Из того же набора12

tailwind-v4 Скилл для ИИ-агента, который подсказывает, как настроить Tailwind CSS v4: тема в CSS, токены дизайна, цвета OKLCH и тёмная тема. CX Codex +1 812установок react-flow-advanced Скилл учит агента внедрять сложные паттерны в React Flow: группировку узлов, историю отмены действий, автоматическую раскладку через dagre и перетаскивание элементов. CX Codex +1 631установок react-router-v7 Скилл с практиками React Router v7: подсказывает, когда брать loader, Form или fetcher, и как настраивать вложенные маршруты. CX Codex +1 572установок react-flow-architecture Архитектурные подсказки для интерфейсов на React Flow: выбор состояния, интеграций и масштаба node-based приложений. CX Codex +1 529установок vitest-testing Скилл для ИИ-агента: подсказывает, как писать тесты на Vitest — ассерты, моки, асинхронность, конфиг. Пригодится, когда в проекте уже стоит Vitest. CX Codex +1 467установок fastapi-code-review Проверяет сервисы на FastAPI: выявляет синхронные блокировки в асинхронных роутах, пропущенные Depends() и ошибки в Pydantic-моделях. CX Codex +1 382установок shadcn-ui Подсказывает агенту, как собирать компоненты на shadcn/ui: Radix, Tailwind, CVA-варианты и data-slot. CX Codex +1 351установок react-flow-code-review Проверяет код на @xyflow/react по чек-листу: антипаттерны, лишние ре-рендеры, типы. Пригодится, когда граф тормозит или ноды пересоздаются. CX Codex +1 319установок

Спонсоры проекта

Компании, которые помогают держать аналитику открытой