
React Flow Code Review
Run a structured React Flow (@xyflow/react) review before merge when your solo app uses node editors, diagrams, or flow builders.
Install
npx skills add https://github.com/existential-birds/beagle --skill react-flow-code-reviewWhat is this skill?
- Five sequenced review gates from locating flow code through checklist closure
- Provider-boundary checks for useReactFlow vs ReactFlowProvider with file:line citations
- Stable nodeTypes/edgeTypes and memo surfaces flagged when recreated each render
- Performance and anti-pattern checklists with evidence required for critical/high findings
- Scoped search for ReactFlow, nodeTypes, edgeTypes, and @xyflow/react imports
Adoption & trust: 1 installs on skills.sh; 62 GitHub stars; 3/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
Recommended Skills
Improve Codebase Architecturemattpocock/skills
Zoom Outmattpocock/skills
Caveman Reviewjuliusbrussee/caveman
Requesting Code Reviewobra/superpowers
Receiving Code Reviewobra/superpowers
Request Refactor Planmattpocock/skills
Journey fit
Common Questions / FAQ
Is React Flow Code Review safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - React Flow Code Review
# React Flow Code Review When reviewing React Flow code, complete the gates below in order. Each step has an objective pass condition before moving on. ## Review gates (sequenced) 1. **Locate flow code** — Search the review scope for `ReactFlow`, `ReactFlowProvider`, `useReactFlow`, `@xyflow/react`, `nodeTypes`, and `edgeTypes`. **Pass:** a short list of file paths (or explicit “none in scope” after searching). 2. **Provider boundary** — For each `useReactFlow()` (and other hooks that require the provider), trace the component tree to an enclosing `ReactFlowProvider`, or record a concrete mismatch with **file:line**. 3. **Stable types and memo surfaces** — For each custom node or edge component, note whether it uses `memo` and typed props (`NodeProps<...>`, etc.). For each `nodeTypes` / `edgeTypes` value passed into `<ReactFlow>`, confirm a stable reference (module scope, or `useMemo` with deps you can point to) or flag unstable recreation with **file:line**. 4. **Report with evidence** — For each finding you will deliver, record **file path and line number(s)** (or a minimal quoted snippet). **Pass:** no critical or high-severity issue is stated without that citation. 5. **Close the checklists** — Use [Performance Checklist](#performance-checklist) and [Common Mistakes](#common-mistakes); each item is **satisfied**, **not applicable** (with reason), or **open** with evidence. **Pass:** no item left silently ambiguous. ## 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 updates. ```tsx // BAD - new object reference every time setNodes(nodes.map(n => ({ ...n, data: { ...n.data, config: { nested: 'value' } } // New object each time }))); // GOOD - use updateNodeData for targeted updates const { updateNodeData } = useReactFlow(); updateNodeData(nodeId, { config: { nested: 'value' } }