I use react-flow-render package. I want to add a new node between two nodes, after clicking on the label ( Edge ).
To add a new Node, it is necessary to have the sourceHandle, targetHandle , source , target
[]
Attention: My Node can have multiple Handles
customNode.tsx
import { CSSProperties, FC, Fragment, memo, useMemo } from 'react'
import { Handle, NodeProps, Position } from 'react-flow-renderer'
interface CustomNodeProps {
label: string
description?: string
target: number
source: number
icon: string
style: CSSProperties | undefined
className?: string
}
const CustomNode: FC<NodeProps<CustomNodeProps>> = ({ isConnectable, data, id, selected }) => {
const targetHandles = useMemo(
() =>
!!data.target &&
Array(data.target)
.fill(0)
.map((_, i) => {
const handleId = `target-handle-${i + 1}`
return (
<Fragment key={handleId}>
<Handle id={handleId} isConnectable={isConnectable} position={Position.Top} type='target' />
</Fragment>
)
}),
[],
)
const sourceHandles = useMemo(
() =>
!!data.source &&
Array(data.source)
.fill(0)
.map((_, i) => {
const handleId = `source-handle-${i + 1}`
return (
<Fragment key={handleId}>
<Handle id={handleId} isConnectable={isConnectable} position={Position.Bottom} type='source' />
</Fragment>
)
}),
[],
)
return (
<>
<div>{targetHandles}</div>
<div
className={`react-flow__node-input ${selected ? 'selected' : ''} ${data?.className ? data.className : ''}`}
style={data.style}
>
<div className='toolbar'>
<button className='toolbar-btn toolbar-btn-danger'>-</button>
</div>
{data.label}
{data.description && <span className='react-flow__node-description'>{data.description}</span>}
</div>
<div>{sourceHandles}</div>
</>
)
}
export default memo(CustomNode)
customEdge.tsx
import { EdgeProps, getEdgeCenter, getSmoothStepPath } from 'react-flow-renderer'
const foreignObjectSize = 40
const Custom = ({
id,
sourceX,
sourceY,
targetX,
targetY,
sourcePosition,
targetPosition,
style = {},
markerEnd,
}: EdgeProps) => {
const edgePath = getSmoothStepPath({
sourceX,
sourceY,
sourcePosition,
targetX,
targetY,
targetPosition,
})
const [edgeCenterX, edgeCenterY] = getEdgeCenter({
sourceX,
sourceY,
targetX,
targetY,
})
return (
<>
<path id={id} style={style} className='react-flow__edge-path' d={edgePath} markerEnd={markerEnd} />
<foreignObject
width={foreignObjectSize}
height={foreignObjectSize}
x={edgeCenterX - foreignObjectSize / 2}
y={edgeCenterY - foreignObjectSize / 2 + 10}
requiredExtensions='http://www.w3.org/1999/xhtml'
>
<div className='wrapper'>
<button className='edge-btn edge-btn-danger'>×</button>
<button className='edge-btn edge-btn-success'>+</button>
</div>
</foreignObject>
</>
)
}
export default Custom