常见错误
🌐 Common Errors
本指南包含在使用 React Flow 时可能出现的警告和错误。我们还收集了来自我们的Discord 服务器 、Github 问题 和Github 讨论 的常见问题和陷阱。
🌐 This guide contains warnings and errors that can occur when using React Flow. We are also adding common questions and pitfalls that we collect from our Discord Server , Github Issues and Github Discussions .
警告:似乎你没有将 zustand 提供者用作祖级。
🌐 Warning: Seems like you have not used zustand provider as an ancestor.
这通常发生在以下情况下:
🌐 This usually happens when:
A: 你安装了两个不同版本的 @reactflow/core。
B: 你正在尝试在 React Flow 上下文之外访问内部 React Flow 状态。
A 的解决方案
🌐 Solution for A
更新 reactflow 和 @reactflow/node-resizer(如果你正在使用它),删除 node_modules 和 package-lock.json,然后重新安装依赖。
🌐 Update reactflow and @reactflow/node-resizer (in case you are using it), remove node_modules and package-lock.json and reinstall the dependencies.
B 的解决方案
🌐 Solution for B
一个可能的解决方案是将你的组件封装在 <ReactFlowProvider /> 中,或者将访问状态的代码移动到你的 React Flow 实例的子组件中。
🌐 A possible solution is to wrap your component with a
<ReactFlowProvider /> or move the code that is
accessing the state inside a child of your React Flow instance.
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
function FlowWithoutProvider(props) {
// cannot access the state here
const reactFlowInstance = useReactFlow();
return <ReactFlow {...props} />;
}
export default FlowWithoutProvider;import { ReactFlow, ReactFlowProvider } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
function Flow(props) {
// still cannot access the state here
// only child components of this component can access the state
const reactFlowInstance = useReactFlow();
return (
<ReactFlowProvider>
<ReactFlow {...props} />
</ReactFlowProvider>
);
}
export default FlowWithProvider;一旦你想要访问 React Flow 的内部状态(例如通过使用 useReactFlow 钩子),你需要使用 <ReactFlowProvider /> 封装你的组件。这里的封装是在组件外部完成的:
🌐 As soon as you want to access the internal state of React Flow (for example by using the
useReactFlow hook), you need to wrap your component with a <ReactFlowProvider />. Here
the wrapping is done outside of the component:
import { ReactFlow, ReactFlowProvider } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
function Flow(props) {
// you can access the internal state here
const reactFlowInstance = useReactFlow();
return <ReactFlow {...props} />;
}
// wrapping with ReactFlowProvider is done outside of the component
function FlowWithProvider(props) {
return (
<ReactFlowProvider>
<Flow {...props} />
</ReactFlowProvider>
);
}
export default FlowWithProvider;你似乎创建了一个新的 nodeTypes 或 edgeTypes 对象。
🌐 It looks like you have created a new nodeTypes or edgeTypes object.
如果这不是故意的,请在组件外定义 nodeTypes/edgeTypes 或对它们进行记忆化。
🌐 If this wasn’t on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.
当 nodeTypes 或 edgeTypes 属性在初始渲染后发生变化时,会出现此警告。nodeTypes 或 edgeTypes 通常只有在极少数情况下才应动态更改。通常,它们会被定义一次,与你在应用中使用的所有类型一起定义。很容易发生的情况是,你在组件的渲染函数内部定义了 nodeTypes 或 edgeTypes 对象,这会导致每次组件重新渲染时 React Flow 都重新渲染。
🌐 This warning appears when the nodeTypes or edgeTypes properties change after the
initial render. The nodeTypes or edgeTypes should only be changed dynamically in very
rare cases. Usually, they are defined once, along with all the types you use in your
application. It can happen easily that you are defining the nodeTypes or edgeTypes object
inside of your component render function, which will cause React Flow to re-render every
time your component re-renders.
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import MyCustomNode from './MyCustomNode';
function Flow(props) {
// new object being created on every render
// causing unnecessary re-renders
const nodeTypes = {
myCustomNode: MyCustomNode,
};
return <ReactFlow nodeTypes={nodeTypes} />;
}
export default Flow;import { ReactFlow } from '@xyflow/react';
import MyCustomNode from './MyCustomNode';
// defined outside of the component
const nodeTypes = {
myCustomNode: MyCustomNode,
};
function Flow(props) {
return <ReactFlow nodeTypes={nodeTypes} />;
}
export default Flow;如果你想动态更改你的 nodeTypes 而不引起不必要的重新渲染,你可以使用这个。
🌐 You can use this if you want to change your nodeTypes dynamically without causing unnecessary re-renders.
import { useMemo } from 'react';
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import MyCustomNode from './MyCustomNode';
function Flow(props) {
const nodeTypes = useMemo(
() => ({
myCustomNode: MyCustomNode,
}),
[],
);
return <ReactFlow nodeTypes={nodeTypes} />;
}
export default Flow;未找到节点类型。正在使用备用类型“default”。
🌐 Node type not found. Using fallback type “default”.
当你为某个节点指定了自定义节点类型,但没有将正确的 nodeTypes 属性传递给 React Flow 时,通常会发生这种情况。自定义节点的 type 选项的字符串需要与 nodeTypes 对象的键完全相同。
🌐 This usually happens when you specify a custom node type for one of your nodes but do not pass the correct nodeTypes property to React Flow. The string for the type option of your custom node needs to be exactly the same as the key of the nodeTypes object.
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import MyCustomNode from './MyCustomNode';
const nodes = [
{
id: 'mycustomnode',
type: 'custom',
// ...
},
];
function Flow(props) {
// nodeTypes property is missing, so React Flow cannot find the custom node component to render
return <ReactFlow nodes={nodes} />;
}import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import MyCustomNode from './MyCustomNode';
const nodes = [
{
id: 'mycustomnode',
type: 'custom',
// ...
},
];
const nodeTypes = {
Custom: MyCustomNode,
};
function Flow(props) {
// node.type and key in nodeTypes object are not exactly the same (capitalized)
return <ReactFlow nodes={nodes} nodeTypes={nodeTypes} />;
}import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
import MyCustomNode from './MyCustomNode';
const nodes = [
{
id: 'mycustomnode',
type: 'custom',
// ...
},
];
const nodeTypes = {
custom: MyCustomNode,
};
function Flow(props) {
return <ReactFlow nodes={nodes} nodeTypes={nodeTypes} />;
}React Flow 父容器需要宽度和高度来渲染图形。
🌐 The React Flow parent container needs a width and a height to render the graph.
在底层,React Flow 会测量父级 DOM 元素以调整渲染器。如果你尝试在没有高度的普通 div 中渲染 React Flow,我们将无法显示图表。如果你遇到此警告,你需要确保你的封装组件具有一些附加的 CSS,以便它获得固定高度或继承其父元素的高度。
🌐 Under the hood, React Flow measures the parent DOM element to adjust the renderer. If you try to render React Flow in a regular div without a height, we cannot display the graph. If you encounter this warning, you need to make sure that your wrapper component has some CSS attached to it so that it gets a fixed height or inherits the height of its parent.
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
function Flow(props) {
return (
<div>
<ReactFlow {...props} />
</div>
);
}import { ReactFlow } from '@xyflow/react';
function Flow(props) {
return (
<div style={{ height: 800 }}>
<ReactFlow {...props} />
</div>
);
}只有子节点可以使用父范围。
🌐 Only child nodes can use a parent extent.
当你试图将 extent 选项添加到没有父节点的节点时,会显示此警告。根据你的操作,你可以删除 extent 选项或指定一个 parentNode。
🌐 This warning appears when you are trying to add the extent option to a node that does
not have a parent node. Depending on what you are trying to do, you can remove the
extent option or specify a parentNode.
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const nodes = [
{
id: 'mycustomnode',
extent: 'parent',
// ...
},
];
function Flow(props) {
return <ReactFlow nodes={nodes} />;
}const nodes = [
{
id: 'mycustomnode',
parentNode: 'someothernode',
extent: 'parent',
// ...
},
];
function Flow(props) {
return <ReactFlow nodes={nodes} />;
}无法创建边。边需要一个源节点和一个目标节点。
🌐 Can’t create edge. An edge needs a source and a target.
当你没有向 edge 对象传递 source 和 target 选项时,就会发生这种情况。没有源和目标,edge 无法被渲染。
🌐 This happens when you do not pass a source and a target option to the edge object.
Without the source and target, the edge cannot be rendered.
import { ReactFlow } from '@xyflow/react';
import '@xyflow/react/dist/style.css';
const nodes = [
/* ... */
];
const edges = [
{
nosource: '1',
notarget: '2',
},
];
function Flow(props) {
return <ReactFlow nodes={nodes} edges={edges} />;
}import { ReactFlow } from '@xyflow/react';
const nodes = [
/* ... */
];
const edges = [
{
source: '1',
target: '2',
},
];
function Flow(props) {
return <ReactFlow nodes={nodes} edges={edges} />;
}ID 为 “some-id” 的旧边不存在。
🌐 The old edge with id=“some-id” does not exist.
当你尝试重新连接一条边时,可能会发生这种情况,但你想要更新的边已经从状态中移除。这是一种非常罕见的情况。有关实现细节,请参见重新连接边示例。
🌐 This can happen when you are trying to reconnect an edge but the edge you want to update is already removed from the state. This is a very rare case. Please see the Reconnect Edge example for implementation details.
无法为源/目标句柄 ID 创建边: “some-id”;边 ID: “some-id”。
🌐 Couldn’t create edge for source/target handle id: “some-id”; edge id: “some-id”.
如果你正在处理多个句柄,并且通过其 id 属性未找到句柄,或者在程序中添加或删除句柄后未更新节点内部信息,这种情况可能会发生。有关处理多个句柄的示例,请参见自定义节点示例。
🌐 This can happen if you are working with multiple handles and a handle is not found by its
id property or if you haven’t
updated the node internals after adding or removing handles
programmatically. Please see the Custom Node Example for an
example of working with multiple handles.
标记类型不存在。
🌐 Marker type doesn’t exist.
当你尝试指定 React Flow 中未内置的标记类型时,会出现此警告。现有的标记类型已在这里记录。
🌐 This warning occurs when you are trying to specify a marker type that is not built into React Flow. The existing marker types are documented here.
句柄:未找到节点ID。
🌐 Handle: No node id found.
当你尝试在自定义节点组件之外使用 <Handle /> 组件时,会出现此警告。
🌐 This warning occurs when you try to use a <Handle /> component outside of a custom node
component.
使用 webpack 4 构建应用时出现错误。
🌐 I get an error when building my app with webpack 4.
如果你使用的是 webpack 4,则可能会遇到如下错误:
🌐 If you’re using webpack 4, you’ll likely run into an error like this:
ERROR in /node_modules/@reactflow/core/dist/esm/index.js 16:19
Module parse failed: Unexpected token (16:19)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loadersReact Flow 是一个现代的 JavaScript 代码库,并且使用了许多更新的 JavaScript 特性。默认情况下,webpack 4 不会转译你的代码,并且它不知道如何处理 React Flow。
🌐 React Flow is a modern JavaScript code base and makes use of lots of newer JavaScript features. By default, webpack 4 does not transpile your code and it doesn’t know how to handle React Flow.
你需要在你的 webpack 配置中添加一些 babel 插件才能使其工作:
🌐 You need to add a number of babel plugins to your webpack config to make it work:
npm i --save-dev babel-loader@8.2.5 @babel/preset-env @babel/preset-react @babel/plugin-proposal-optional-chaining @babel/plugin-proposal-nullish-coalescing-operator并像这样配置加载器:
🌐 and configure the loader like this:
{
test: /node_modules[\/\\]@?reactflow[\/\\].*.js$/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', "@babel/preset-react"],
plugins: [
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
]
}
}
}如果你使用的是 webpack 5,你无需做任何操作!React Flow 会开箱即用。
当我的节点包含 <canvas /> 元素时,鼠标事件无法一致工作。
🌐 Mouse events aren’t working consistently when my nodes contain a <canvas /> element.
如果你在自定义节点中使用 <canvas /> 元素,你可能会遇到画布鼠标事件中看似不正确的坐标问题。
🌐 If you’re using a <canvas /> element inside your custom node, you might run into
problems with seemingly incorrect coordinates in mouse events from the canvas.
React Flow 使用 CSS 变换来在缩放时调整节点的大小。然而,从 DOM 的角度来看,元素的大小仍然是相同的。如果你有希望计算鼠标相对于画布元素位置的事件监听器,这可能会引起问题。
🌐 React Flow uses CSS transforms to scale nodes as you zoom in and out. However, from the DOM’s perspective, the element is still the same size. This can cause problems if you have event listeners that want to calculate the mouse position relative to the canvas element.
要在你控制的事件处理程序中解决这个问题,你可以将计算出的相对位置按 1 / zoom 缩放,其中 zoom 是流程的当前缩放级别。要获取当前缩放级别,你可以使用 useReactFlow 钩子中的 getZoom 方法。
🌐 To remedy this in event handlers you control, you can scale your computed relative
position by 1 / zoom where zoom is the current zoom level of the flow. To get the
current zoom level, you can use the getZoom method from the
useReactFlow hook.
边缘未显示。
🌐 Edges are not displaying.
如果你的边在 React Flow 中没有显示,这可能是以下原因之一:
🌐 If your edges are not displaying in React Flow, this might be due to one of the following reasons:
- 你尚未导入 React Flow 样式表。如果你还没有导入它,你可以像
import '@xyflow/react/dist/style.css';那样导入它。 - 如果你已将默认节点替换为自定义节点,请检查该自定义节点组件中是否具有适当的
source/target句柄。没有句柄是无法创建边的。 - 如果你使用像 Tailwind 或 Bulma 这样的外部样式库,确保它不会覆盖边缘样式。例如,有时样式库会将
.react-flow__edgesSVG 选择器覆盖为overflow: hidden,这会隐藏边缘。 - 如果你正在使用异步操作,例如向后台发起请求,请确保在异步操作之后调用
useUpdateNodeInternal钩子返回的updateNodeInternals函数,这样 React Flow 才能在内部更新句柄位置。
边缘显示不正确。
🌐 Edges are not displaying correctly.
如果你的边缘没有正常渲染,这可能是以下原因之一:
🌐 If your edges are not rendering as they should, this could be due to one of the following reasons:
- 如果你想隐藏你的账号,不要使用
display: none来隐藏它们。使用opacity: 0或visibility: hidden。 - 如果边缘未连接到正确的节点句柄,请检查是否在自定义节点组件中添加了多个相同类型的句柄(
source或target)。如果是这种情况,请为它们分配 ID。节点上同种类型的多个句柄需要有可区分的 ID,以便 React Flow 知道边缘对应哪个句柄。 - 如果你正在更改句柄的位置(通过重新排序等),请确保在更改后调用
useUpdateNodeInternals钩子返回的updateNodeInternals函数,以便 React Flow 知道在内部更新句柄位置。 - 如果你正在使用自定义边,并且希望你的边从源节点的句柄连接到目标节点的句柄,请确保在边路径创建函数中正确传递从自定义边组件获取的
sourceX, sourceY, targetX, and targetY属性(例如getBezierPath等)。sourceX, sourceY和targetX, targetY分别表示源句柄和目标句柄的x,y坐标。 - 如果来自源端或目标端的自定义边缘没有按照预期朝向节点的句柄(以奇怪的角度进入或离开句柄),请确保在边缘路径创建函数中传递你从自定义边缘组件中获得的
sourcePosition和targetPosition属性(例如,getBezierPath)。在路径创建函数中传递源/目标句柄位置对于边缘正确从句柄开始或结束是必要的。