トラブルシューティング
このガイドには、React Flowを使用する際に発生する可能性のある警告とエラーが含まれています。Discordサーバー、Github Issues、Github Discussionsから収集したよくある質問や落とし穴も追加しています。
警告: zustand プロバイダーを祖先として使用していないようです
これは通常、次の場合に発生します。
A: @reactflow/core の異なるバージョンが2つインストールされています。
B: React Flow のコンテキストの外で、React Flow の内部状態にアクセスしようとしています。
ソリューション A
reactflow と @reactflow/node-resizer(使用している場合)を更新し、node_modules と package-lock.json を削除して、依存関係を再インストールします。
ソリューション B
可能な解決策として、コンポーネントを <ReactFlowProvider />
でラップするか、状態にアクセスするコードを React Flow インスタンスの子の中に移動します。
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 />
でラップする必要があります。ここでは、コンポーネントの外側でラップが行われています。
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 オブジェクトを作成したようです。意図的なものでなければ
コンポーネントの外側で nodeTypes/edgeTypes を定義するか、メモ化してください。
この警告は、nodeTypes
または edgeTypes
プロパティが最初のレンダリング後に変更された場合に表示されます。 nodeTypes
または edgeTypes
は、非常にまれな場合にのみ動的に変更する必要があります。通常、それらはアプリケーションで使用しているすべてのタイプで一度定義されます。コンポーネントのレンダリング関数内で nodeTypes または edgeTypes オブジェクトを定義すると、コンポーネントが再レンダリングされるたびに React Flow が再レンダリングされるため、簡単に発生する可能性があります。
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 unneccessary 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 を動的に変更したい場合に使用できます。
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」というフォールバックタイプを使用します。
これは通常、ノードのいずれかにカスタムノードタイプを指定しているが、正しい nodeTypes プロパティを React Flow に渡していない場合に発生します。カスタムノードの type オプションの文字列は、nodeTypes オブジェクトのキーと完全に一致する必要があります。
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 の親コンテナには、グラフをレンダリングするための幅と高さが必要です。
内部的に、React Flow は親 DOM 要素を測定してレンダラーを調整します。高さを指定せずに通常の div に React Flow をレンダリングしようとすると、グラフを表示できません。この警告が発生した場合は、ラッパーコンポーネントに何らかの CSS を適用して、固定の高さを取得するか、親の高さを継承するようにする必要があります。
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>
);
}
子ノードのみが親範囲を使用できます。
この警告は、親ノードを持たないノードにextent
オプションを追加しようとした場合に表示されます。何を行おうとしているかに応じて、extent
オプションを削除するか、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} />;
}
エッジを作成できません。エッジにはソースとターゲットが必要です。
これは、エッジオブジェクトにsource
とtarget
オプションを渡さない場合に発生します。ソースとターゲットがないと、エッジをレンダリングできません。
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」の古いエッジは存在しません。
これは、エッジを再接続しようとした場合に、更新しようとしているエッジが既に状態から削除されている場合に発生する可能性があります。これは非常にまれなケースです。エッジの再接続例を実装の詳細についてはご覧ください。
ソース/ターゲットハンドルID:「some-id」、エッジID:「some-id」のエッジを作成できませんでした。
これは、複数のハンドルを使用していて、id
プロパティでハンドルが見つからない場合、またはプログラムでハンドルを追加または削除した後にノードの内部を更新していない場合に発生する可能性があります。カスタムノードの例で、複数のハンドルを使用する例を参照してください。
マーカータイプが存在しません。
この警告は、React Flowに組み込まれていないマーカータイプを指定しようとしたときに発生します。既存のマーカータイプはこちらで説明されています。
ハンドル:ノードIDが見つかりません。
この警告は、カスタムノードコンポーネントの外で<Handle />
コンポーネントを使用しようとすると発生します。
Webpack 4でアプリをビルドするときにエラーが発生します。
Webpack 4を使用している場合、このようなエラーが発生する可能性があります。
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.dokyumento.jp/concepts#loaders
React Flowは最新のJavaScriptコードベースであり、多くの新しいJavaScript機能を使用しています。デフォルトでは、Webpack 4はコードを変換せず、React Flowの処理方法を認識しません。
動作させるには、Webpackの設定にいくつかのBabelプラグインを追加する必要があります。
$ 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
そして、ローダーを次のように設定します。
{
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 />
要素が含まれている場合、マウスイベントが安定して動作しません。
カスタムノード内に<canvas />
要素を使用している場合、canvasからのマウスイベントで座標が正しくないように見える問題が発生する可能性があります。
React Flowは、ズームインとズームアウト時にノードをスケーリングするためにCSS変換を使用します。しかし、DOMの観点からは、要素のサイズは同じままです。canvas要素に対するマウス位置を計算しようとするイベントリスナーがある場合、問題が発生する可能性があります。
この問題を解決するには、制御するイベントハンドラーで、計算された相対位置を1 / zoom
でスケーリングします。ここでzoom
はフローの現在のズームレベルです。getZoom
メソッドを使用して現在のズームレベルを取得できます。useReactFlow
フックを使用します。