Loading...
Loading...
Compare original and translation side by side
// 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} />;
}// 错误示例 - 每次渲染都会重新创建对象
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} />;
}// 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>;
});// 错误示例 - 未使用记忆化
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>;
});// 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} />// 错误示例 - 内联回调
<ReactFlow
onNodesChange={(changes) => setNodes(applyNodeChanges(changes, nodes))}
/>
// 正确示例 - 记忆化回调
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>
);
}// 错误示例 - 会抛出错误
function App() {
const { getNodes } = useReactFlow(); // 错误:无Provider包裹
return <ReactFlow ... />;
}
// 正确示例 - 用Provider包裹
function FlowContent() {
const { getNodes } = useReactFlow(); // 正常工作
return <ReactFlow ... />;
}
function App() {
return (
<ReactFlowProvider>
<FlowContent />
</ReactFlowProvider>
);
}// 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' } });// 错误示例 - 每次都创建新对象引用
setNodes(nodes.map(n => ({
...n,
data: { ...n.data, config: { nested: 'value' } } // 每次生成新对象
})));
// 正确示例 - 使用updateNodeData进行针对性更新
const { updateNodeData } = useReactFlow();
updateNodeData(nodeId, { config: { nested: 'value' } });memo()useMemouseCallbackmemo()useMemouseCallbackmemo()memo()setNodes((nds) => ...)updateNodeDatasetNodes((nds) => ...)updateNodeDatafitView()fitViewOptionsfitView()fitViewOptions// 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>// 错误示例 - 无高度,Flow无法渲染
<ReactFlow nodes={nodes} edges={edges} />
// 正确示例 - 显式设置尺寸
<div style={{ width: '100%', height: '100vh' }}>
<ReactFlow nodes={nodes} edges={edges} />
</div>// Required for default styles
import '@xyflow/react/dist/style.css';// 需要导入默认样式
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>// 错误示例 - 点击按钮会拖动节点
<button onClick={handleClick}>点击</button>
// 正确示例 - 阻止拖动
<button className="nodrag" onClick={handleClick}>点击</button>// BAD - string literals
<Handle type="source" position="right" />
// GOOD - type-safe constants
import { Position } from '@xyflow/react';
<Handle type="source" position={Position.Right} />// 错误示例 - 使用字符串字面量
<Handle type="source" position="right" />
// 正确示例 - 类型安全的常量
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
));// 错误示例 - 直接修改
nodes[0].position = { x: 100, y: 100 };
setNodes(nodes);
// 正确示例 - 不可变更新
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);// 错误示例 - 失去类型安全
const [nodes, setNodes] = useNodesState(initialNodes);
// 正确示例 - 显式声明类型
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>) { ... }// 错误示例 - 使用错误类型
function CustomNode(props: any) { ... }
// 正确示例 - 使用正确的Props类型
function CustomNode(props: NodeProps<MyNode>) { ... }