Search code examples
javascriptreactjscss-positiondraggable

draggable component in react not working as expected


I am trying to make a draggable button using react.

The button drags over the page in a proper manner but when I drop it. Its top and left values become negative(not even reset to their original top:0,left:0) i.e. the component goes out of the page.

code sand box link : code

main draggable.js component:

import React, { Component } from 'react';
import { Button } from '@material-ui/core';

class DraggableButton extends Component {

    constructor() {
        super();
        this.state = {
            dragging: false,
            diffX: 0,
            diffY: 0,
            style: {
                top: 0,
                left: 0
            }
        }
    }

    handleMouseDown = (event) => {
        console.log("element caught");
        this.setState({
            diffX: event.clientX - event.currentTarget.getBoundingClientRect().left,
            diffY: event.clientY - event.currentTarget.getBoundingClientRect().top,
            dragging: true
        })
    }

    handleMouseMove = (event) => {
        if (this.state.dragging) {
            console.log("dragging");
            let left = event.clientX - this.state.diffX;
            let top = event.clientY - this.state.diffY;

            this.setState({
                style: {
                    left,
                    top
                }
            }, console.log("style ", this.state.style))
        }
    }


    handleMouseUp = () => {

        console.log('element released');
        console.log('left value ', this.state.style.left);
        console.log('top value ', this.state.style.top);
        this.setState({
            dragging: false,
        })
    }


    render() {
        return (

            <Button
                variant="contained" color="primary"
                style={{ position: "absolute", ...this.state.style }}
                draggable={true}
                onDragStart={this.handleMouseDown}
                onDrag={this.handleMouseMove}
                onDragEnd={this.handleMouseUp}
            // onMouseDown={this.handleMouseDown}
            // onMouseMove={this.handleMouseMove}
            // onMouseUp={this.handleMouseUp}
            >
                draggable button
            </Button>
        );
    }
}

export default DraggableButton;

console screenshot :

console view

As is visible in the image above at the time of dragging top: 193 left : 309 and as we dropped the element it turned to left: -109 top: -13.

why is this happening how can we fix it ?


Solution

  • In your handleMouseMove you need to check if event.clientX is a positive integer and then change the state, or else it will reduce the diffX value and it will be nevative. (On drag release this becomes 0)

    let left = event.clientX - this.state.diffX;
    
    
    
      handleMouseMove = (event) => {
        if (this.state.dragging) {
          let left = event.clientX - this.state.diffX;
          let top = event.clientY - this.state.diffY;
    
          if (event.clientX !== 0)
            this.setState({
              style: {
                left,
                top
              }
            });
        }
      };