copy the node while drag and drop using react-flow-renderer

Viewed 3834

Iam trying to implement: original node should stay in its position and doing drag and drop on it, has to create a new node at drop location. Original should stay at initial position.

dragging duplicate node should just change its position.

import React, { Component, MouseEvent } from 'react'
import ReactFlow from 'react-flow-renderer'

export default class Platform extends Component {

    constructor(props) {
        super(props)
        
    
        this.state = {
             duplicates : [],
             original: [{id: "original", data: {label: 'original', duplicate: false }, position: {x:100, y:100}, style: this.style}]
        }
    }

    lastId = 0
    style = { background: '#ccc', width: 50, height: 50, borderRadius: 50}


    onNodeDragStart = (evt: MouseEvent, node: Node) => {
    }


    onNodeDragStop = (evt: MouseEvent, node: Node) => {
        if(!node.data.duplicate){
            node.id = (this.lastId++).toString(10)
            node.data.duplicate = true
            node.data.label = "duplicate"
            
            this.setState(prevState => ({
                duplicates: prevState.duplicates.concat(node)
            }))
        }
    }

    
    render() {
        console.log("state: ", this.state)
        const elements = this.state.original.concat(this.state.duplicates)
        const graphStyles = { width: '100%', height: '800px' };

        return (
            <div>
                <ReactFlow  onNodeDragStart={this.onNodeDragStart} onNodeDragStop={this.onNodeDragStop}  style={graphStyles} elements={elements}></ReactFlow>
            </div>
        )
    }
}

The original node initially

After drag and drop to create a duplicate node at drop position. When I see the state of the component it still shows the position of original as position:{x:100, y:100}. But it is not at that position.

How to make original intact while creating a duplicate node? after dragging the original

1 Answers

You have to add the code that will update the position in the state. By default this position is only used when creating new element but then it is not updated. You can solve this by changing your onNodeDragStop handler to something like this:

onNodeDragStop = (evt: MouseEvent, node: Node) => {
    if (!node.data.duplicate) {
        this.setState(prevState => ({
            original: prevState.original.map((n) => {
                if (n.id !== node.id) return node;

                return {
                    ...node,
                    position: {
                        x: node.position.x,
                        y: node.position.y
                    }
                }
            }),
            duplicates: [
                ...prevState.duplicates,
                {
                    ...node,
                    id: (this.lastId++).toString(10),
                    data: {
                        ...node.data,
                        duplicate: true,
                        label: "duplicate"
                    },
                }
            ]
        }))
    }
}

Also, I changed your code to not mutate the original node and instead return a new one with some properties changed.

Related