react-flow-code-review

React Flow Code Review

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-code-review" with this command: npx skills add existential-birds/beagle/existential-birds-beagle-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.

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

  1. Missing memo() on Custom Nodes/Edges

Problem: Custom components re-render on every parent update.

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

  1. Inline Callbacks Without useCallback

Problem: Creates new function references, breaking memoization.

// 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} />

  1. Using useReactFlow Outside Provider

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

  1. Storing Complex Objects in Node Data

Problem: Reference equality checks fail, causing unnecessary updates.

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

Performance Checklist

Node Rendering

  • Custom nodes wrapped in memo()

  • nodeTypes defined outside component or memoized

  • Heavy computations inside nodes use useMemo

  • Event handlers use useCallback

Edge Rendering

  • Custom edges wrapped in memo()

  • edgeTypes defined outside component or memoized

  • Edge path calculations are not duplicated

State Updates

  • Using functional form of setState: setNodes((nds) => ...)

  • Not spreading entire state for single property updates

  • Using updateNodeData for data-only changes

  • Batch updates when adding multiple nodes/edges

Viewport

  • Not calling fitView() on every render

  • Using fitViewOptions for initial fit only

  • Animation durations are reasonable (< 500ms)

Common Mistakes

Missing Container Height

// BAD - no height, flow won't render <ReactFlow nodes={nodes} edges={edges} />

// GOOD - explicit dimensions <div style={{ width: '100%', height: '100vh' }}> <ReactFlow nodes={nodes} edges={edges} /> </div>

Missing CSS Import

// Required for default styles import '@xyflow/react/dist/style.css';

Forgetting nodrag on Interactive Elements

// BAD - clicking button drags node <button onClick={handleClick}>Click</button>

// GOOD - prevents drag <button className="nodrag" onClick={handleClick}>Click</button>

Not Using Position Constants

// BAD - string literals <Handle type="source" position="right" />

// GOOD - type-safe constants import { Position } from '@xyflow/react'; <Handle type="source" position={Position.Right} />

Mutating Nodes/Edges Directly

// BAD - direct mutation nodes[0].position = { x: 100, y: 100 }; setNodes(nodes);

// GOOD - immutable update setNodes(nodes.map(n => n.id === '1' ? { ...n, position: { x: 100, y: 100 } } : n ));

TypeScript Issues

Missing Generic Types

// BAD - loses type safety const [nodes, setNodes] = useNodesState(initialNodes);

// GOOD - explicit types type MyNode = Node<{ value: number }, 'custom'>; const [nodes, setNodes] = useNodesState<MyNode>(initialNodes);

Wrong Props Type

// BAD - using wrong type function CustomNode(props: any) { ... }

// GOOD - correct props type function CustomNode(props: NodeProps<MyNode>) { ... }

Review Questions

  • Are all custom components memoized?

  • Are nodeTypes/edgeTypes defined outside render?

  • Are callbacks wrapped in useCallback?

  • Is the container sized properly?

  • Are styles imported?

  • Is useReactFlow used inside a provider?

  • Are interactive elements marked with nodrag?

  • Are types used consistently throughout?

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.

Coding

langgraph-code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

docling

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

python-code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

fastapi-code-review

No summary provided by upstream source.

Repository SourceNeeds Review