Reviews React Flow code for anti-patterns, performance issues, and best practices. Use when reviewing code that uses @xyflow/react, checking for common mistakes, or optimizing node-based UI implementations.
View on GitHubskills/react-flow-code-review/SKILL.md
February 1, 2026
Select agents to install to:
npx add-skill https://github.com/existential-birds/beagle/blob/main/skills/react-flow-code-review/SKILL.md -a claude-code --skill react-flow-code-reviewInstallation paths:
.claude/skills/react-flow-code-review/# React Flow Code Review
## Critical Anti-Patterns
### 1. Defining nodeTypes/edgeTypes Inside Components
**Problem**: Causes all nodes to re-mount on every render.
```tsx
// BAD - recreates object every render
function Flow() {
const nodeTypes = { custom: CustomNode }; // WRONG
return <ReactFlow nodeTypes={nodeTypes} />;
}
// GOOD - defined outside component
const nodeTypes = { custom: CustomNode };
function Flow() {
return <ReactFlow nodeTypes={nodeTypes} />;
}
// GOOD - useMemo if dynamic
function Flow() {
const nodeTypes = useMemo(() => ({ custom: CustomNode }), []);
return <ReactFlow nodeTypes={nodeTypes} />;
}
```
### 2. Missing memo() on Custom Nodes/Edges
**Problem**: Custom components re-render on every parent update.
```tsx
// BAD - no memoization
function CustomNode({ data }: NodeProps) {
return <div>{data.label}</div>;
}
// GOOD - wrapped in memo
import { memo } from 'react';
const CustomNode = memo(function CustomNode({ data }: NodeProps) {
return <div>{data.label}</div>;
});
```
### 3. Inline Callbacks Without useCallback
**Problem**: Creates new function references, breaking memoization.
```tsx
// BAD - inline callback
<ReactFlow
onNodesChange={(changes) => setNodes(applyNodeChanges(changes, nodes))}
/>
// GOOD - memoized callback
const onNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[]
);
<ReactFlow onNodesChange={onNodesChange} />
```
### 4. Using useReactFlow Outside Provider
```tsx
// BAD - will throw error
function App() {
const { getNodes } = useReactFlow(); // ERROR: No provider
return <ReactFlow ... />;
}
// GOOD - wrap in provider
function FlowContent() {
const { getNodes } = useReactFlow(); // Works
return <ReactFlow ... />;
}
function App() {
return (
<ReactFlowProvider>
<FlowContent />
</ReactFlowProvider>
);
}
```
### 5. Storing Complex Objects in Node Data
**Problem**: Reference equality checks fail, causing unnecessary update