自訂節點
React Flow 的一個強大功能是能夠新增自訂節點。在自訂節點中,您可以渲染任何您想要的東西。您可以定義多個來源和目標控制點,並渲染表單輸入或圖表等。在本節中,我們將實作一個具有輸入欄位的節點,該欄位會更新應用程式另一部分中的一些文字。
實作自訂節點
自訂節點是一個 React 元件,它被包裝起來以提供基本功能,例如選取或拖曳。從包裝元件中,我們傳遞屬性,例如位置或資料,以及其他屬性。讓我們開始實作 TextUpdaterNode
。我們使用 Handle
元件,以便能夠將我們的自訂節點與其他節點連接,並將輸入欄位新增至節點
import { useCallback } from 'react';
import { Handle, Position } from '@xyflow/react';
const handleStyle = { left: 10 };
function TextUpdaterNode({ data }) {
const onChange = useCallback((evt) => {
console.log(evt.target.value);
}, []);
return (
<>
<Handle type="target" position={Position.Top} />
<div>
<label htmlFor="text">Text:</label>
<input id="text" name="text" onChange={onChange} className="nodrag" />
</div>
<Handle type="source" position={Position.Bottom} id="a" />
<Handle
type="source"
position={Position.Bottom}
id="b"
style={handleStyle}
/>
</>
);
}
如您所見,我們已將類別名稱「nodrag」新增至輸入。這可以防止在輸入欄位中拖曳,並讓我們選取文字等。
新增節點類型
您可以將新的節點類型新增至 React Flow,方法是將其新增至 nodeTypes
屬性。重要的是,nodeTypes
會進行記憶或在元件外部定義。否則,React 會在每次渲染時建立一個新物件,這會導致效能問題和錯誤。
const nodeTypes = useMemo(() => ({ textUpdater: TextUpdaterNode }), []);
return <ReactFlow nodeTypes={nodeTypes} />;
在定義新的節點類型之後,您可以使用 type
節點選項來使用它
const nodes = [
{
id: 'node-1',
type: 'textUpdater',
position: { x: 0, y: 0 },
data: { value: 123 },
},
];
將所有內容放在一起並新增一些基本樣式後,我們將獲得一個將文字列印到主控台的自訂節點
使用多個控制點
如您所見,我們在節點中新增了兩個來源控制點,使其具有兩個輸出。如果您想要將其他節點與這些特定控制點連接,則節點 ID 不夠,您還需要傳遞特定控制點 ID。在此情況下,一個控制點的 ID 為 "a"
,另一個控制點的 ID 為 "b"
。控制點特定的邊緣使用 sourceHandle
或 targetHandle
選項,這些選項會參照節點中的控制點
const initialEdges = [
{ id: 'edge-1', source: 'node-1', sourceHandle: 'a', target: 'node-2' },
{ id: 'edge-2', source: 'node-1', sourceHandle: 'b', target: 'node-3' },
];
在此情況下,來源節點是兩個控制點的 node-1
,但控制點 ID 不同。一個來自控制點 ID "a"
,另一個來自 "b"
。兩個邊緣也具有不同的目標節點
請注意,如果您是以程式方式變更自訂節點中控制點的位置或數量,則需要使用 useUpdateNodeInternals
hook,以正確通知 ReactFlow 變更。從這裡,您應該能夠建置您的自訂節點。在大多數情況下,我們建議僅使用自訂節點。內建的節點僅為基本範例。您可以在自訂節點 API 區段中找到已傳遞屬性的清單和更多資訊。