react-flow-code-review by existential-birds/beagle
npx skills add https://github.com/existential-birds/beagle --skill react-flow-code-review问题:导致所有节点在每次渲染时都重新挂载。
// 错误 - 每次渲染都重新创建对象
function Flow() {
const nodeTypes = { custom: CustomNode }; // 错误
return <ReactFlow nodeTypes={nodeTypes} />;
}
// 正确 - 在组件外部定义
const nodeTypes = { custom: CustomNode };
function Flow() {
return <ReactFlow nodeTypes={nodeTypes} />;
}
// 正确 - 如果是动态的,使用 useMemo
function Flow() {
const nodeTypes = useMemo(() => ({ custom: CustomNode }), []);
return <ReactFlow nodeTypes={nodeTypes} />;
}
问题:自定义组件在父组件每次更新时都会重新渲染。
// 错误 - 没有记忆化
function CustomNode({ data }: NodeProps) {
return <div>{data.label}</div>;
}
// 正确 - 用 memo 包装
import { memo } from 'react';
const CustomNode = memo(function CustomNode({ data }: NodeProps) {
return <div>{data.label}</div>;
});
问题:创建新的函数引用,破坏了记忆化。
// 错误 - 内联回调
<ReactFlow
onNodesChange={(changes) => setNodes(applyNodeChanges(changes, nodes))}
/>
// 正确 - 记忆化的回调
const onNodesChange = useCallback(
(changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
[]
);
<ReactFlow onNodesChange={onNodesChange} />
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
// 错误 - 会抛出错误
function App() {
const { getNodes } = useReactFlow(); // 错误:没有提供者
return <ReactFlow ... />;
}
// 正确 - 包装在提供者中
function FlowContent() {
const { getNodes } = useReactFlow(); // 正常工作
return <ReactFlow ... />;
}
function App() {
return (
<ReactFlowProvider>
<FlowContent />
</ReactFlowProvider>
);
}
问题:引用相等性检查失败,导致不必要的更新。
// 错误 - 每次都创建新的对象引用
setNodes(nodes.map(n => ({
...n,
data: { ...n.data, config: { nested: 'value' } } // 每次都创建新对象
})));
// 正确 - 使用 updateNodeData 进行针对性更新
const { updateNodeData } = useReactFlow();
updateNodeData(nodeId, { config: { nested: 'value' } });
memo() 包装useMemouseCallbackmemo() 包装setNodes((nds) => ...)updateNodeDatafitView()fitViewOptions// 错误 - 没有高度,流程图不会渲染
<ReactFlow nodes={nodes} edges={edges} />
// 正确 - 明确的尺寸
<div style={{ width: '100%', height: '100vh' }}>
<ReactFlow nodes={nodes} edges={edges} />
</div>
// 默认样式所必需
import '@xyflow/react/dist/style.css';
// 错误 - 点击按钮会拖动节点
<button onClick={handleClick}>点击</button>
// 正确 - 防止拖动
<button className="nodrag" onClick={handleClick}>点击</button>
// 错误 - 字符串字面量
<Handle type="source" position="right" />
// 正确 - 类型安全的常量
import { Position } from '@xyflow/react';
<Handle type="source" position={Position.Right} />
// 错误 - 直接修改
nodes[0].position = { x: 100, y: 100 };
setNodes(nodes);
// 正确 - 不可变更新
setNodes(nodes.map(n =>
n.id === '1' ? { ...n, position: { x: 100, y: 100 } } : n
));
// 错误 - 失去类型安全
const [nodes, setNodes] = useNodesState(initialNodes);
// 正确 - 显式类型
type MyNode = Node<{ value: number }, 'custom'>;
const [nodes, setNodes] = useNodesState<MyNode>(initialNodes);
// 错误 - 使用错误的类型
function CustomNode(props: any) { ... }
// 正确 - 正确的 props 类型
function CustomNode(props: NodeProps<MyNode>) { ... }
每周安装量
123
代码仓库
GitHub 星标数
41
首次出现
2026年1月20日
安全审计
安装于
opencode102
gemini-cli99
codex97
github-copilot87
cursor85
claude-code84
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} />;
}
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>;
});
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} />
// 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>
);
}
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' } });
memo()useMemouseCallbackmemo()setNodes((nds) => ...)updateNodeData for data-only changesfitView() on every renderfitViewOptions for initial fit only// 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>
// Required for default styles
import '@xyflow/react/dist/style.css';
// BAD - clicking button drags node
<button onClick={handleClick}>Click</button>
// GOOD - prevents drag
<button className="nodrag" onClick={handleClick}>Click</button>
// BAD - string literals
<Handle type="source" position="right" />
// GOOD - type-safe constants
import { Position } from '@xyflow/react';
<Handle type="source" position={Position.Right} />
// 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
));
// BAD - loses type safety
const [nodes, setNodes] = useNodesState(initialNodes);
// GOOD - explicit types
type MyNode = Node<{ value: number }, 'custom'>;
const [nodes, setNodes] = useNodesState<MyNode>(initialNodes);
// BAD - using wrong type
function CustomNode(props: any) { ... }
// GOOD - correct props type
function CustomNode(props: NodeProps<MyNode>) { ... }
Weekly Installs
123
Repository
GitHub Stars
41
First Seen
Jan 20, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode102
gemini-cli99
codex97
github-copilot87
cursor85
claude-code84
GSAP React 动画库使用指南:useGSAP Hook 与最佳实践
3,400 周安装
Datadog自动化监控:通过Rube MCP与Composio实现指标、日志、仪表板管理
69 周安装
Intercom自动化指南:通过Rube MCP与Composio实现客户支持对话管理
69 周安装
二进制初步分析指南:使用ReVa工具快速识别恶意软件与逆向工程
69 周安装
PrivateInvestigator 道德人员查找工具 | 公开数据调查、反向搜索与背景研究
69 周安装
TorchTitan:PyTorch原生分布式大语言模型预训练平台,支持4D并行与H100 GPU加速
69 周安装
screenshot 截图技能:跨平台桌面截图工具,支持macOS/Linux权限管理与多模式捕获
69 周安装