3

Based on the create-react-app template, I'm trying to implement a very basic drag / drop scenario. My App.js currently looks like this:

import React, { Component } from 'react';
import './App.css';

class App extends Component {
  render() {
    const myStyle = {
      height: '100px',
      width: '200px',
      top: '50px',
      left: '100px',
      position: 'absolute',
      borderStyle: 'solid',
      borderColor: 'blue',      
    };

    return (

      <div className="App">        
          <div style={myStyle} draggable>test</div>
          <div>test2</div>        
      </div>
    );
  }
}

export default App;

My question is that, from all the tutorials and documentation that I've seen, I understood the addition of the draggable property to cause the element to be draggable, however, it is not.

What additional properties need to be set to make an object draggable? (I'm not interested in dropping anything at this stage.)

3
  • Did you try draggable="true"? Commented Jan 7, 2019 at 15:56
  • I didn't - but I just have it it makes no difference Commented Jan 7, 2019 at 16:19
  • Does this answer your question? Recommended way of making React component/div draggable Commented Oct 11, 2021 at 10:08

3 Answers 3

5

This can be a core implementation of the drag behaviour in React. It needs enhancements of course, plus does not handle dropping yet:

const { useRef } = React

const App = () => {
  const elemRef = useRef(null)
  const dragProps = useRef()
  
  const initialiseDrag = event => {
    const { target, clientX, clientY } = event
    const { offsetTop, offsetLeft } = target
    const { left, top } = elemRef.current.getBoundingClientRect()
    
    dragProps.current = {
      dragStartLeft: left - offsetLeft,
      dragStartTop: top - offsetTop,
      dragStartX: clientX,
      dragStartY: clientY
    }
    window.addEventListener('mousemove', startDragging, false)
    window.addEventListener('mouseup', stopDragging, false)
  }
  
  
  const startDragging = ({ clientX, clientY }) => {    
    elemRef.current.style.transform = `translate(${dragProps.current.dragStartLeft + clientX - dragProps.current.dragStartX}px, ${dragProps.current.dragStartTop + clientY - dragProps.current.dragStartY}px)`
  } 

  const stopDragging = () => {
    window.removeEventListener('mousemove', startDragging, false)
    window.removeEventListener('mouseup', stopDragging, false)
  }
  
  return (
    <div
      onMouseDown={initialiseDrag}
      ref={elemRef}
      >
      DragMe
    </div>
  )
}

ReactDOM.render(<App />, document.getElementById('root'));
div {
  cursor: grab;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Sign up to request clarification or add additional context in comments.

6 Comments

I realise I could roll my own implementation, but I thought it should be possible to use the draggable property. Are you saying that React doesn't work with the draggable property built into HTML5?
draggable do work in react too but this implementation gives you more control over the drag coordinates for further processing.
I've realised that I probably will need to end up with something like this, so it is very useful... I would still like to know why draggable doesn't work, though
Nice. If you are satisfied with the answer, please, upvote it. If entirely solves your problem also please mark it as accepted answer. Thanks in advance. Concering the draggable unfortunatelly I do not have too many experience, but as it is a native browser feature it do not allow too much control via javascript I think.
This helped me to implement a custom range slider(without using an input type range), Thank you!
|
0

As I cannot run your current ReactJS application, I have pieced together a short example to show different instances of the drag and drop functionality.

As you can see by the example setting the draggable attribute to your element should make the element draggable, as it would look dragging an image on a typical webpage.

Can you confirm that when dragging your element, it doesn't move at all as seen in the code snippet for the not draggable box?

var draggable = document.getElementById('draggable');

function onDragStart(event) {
    event.dataTransfer.setData('text/html', null); //cannot be empty string
    var counter = document.getElementById('counter');
    counter.innerText = parseInt(counter.innerText, 10) + 1;
}

draggable.addEventListener('dragstart', onDragStart, false);
#draggable{
    width: 100px;
    height: 100px;
    background: blue;
    margin: 10px 5px;
}

#notdraggable{
    width: 100px;
    height: 100px;
    background: red;
    margin: 10px 5px;
}

#draggableNDT{
      width: 100px;
    height: 100px;
    background: green;
    margin: 10px 5px;
} 
   <div>Draggable (<span id='counter'>0</span>)</div>
    <div id='draggable' draggable='true'></div>
    
    <div><pre>Draggable (No DataTransfer)</div>
    <div id='draggableNDT' draggable></div>
    
    <div><pre>Not Draggable</div>
    <div id='notdraggable' draggable='false'></div>

6 Comments

I'm just providing a complete answer. In the link provided you can also see that you need to create a method for the drag event handler as well as adding the draggable tag to the HTML
It is not a complete answer. And answers pointing to external websites are not answers at all. They should be comments instead
Are you saying that you /need/ to create that handler? I have tried that and it doesn't make a difference, but I was under the impression it was not necessary.
I've updated the answer to a more complete answer, Can you confirm that when dragging your element, it doesn't move at all as seen in the code snippet for the not draggable box?
I do not see the reason why to downvote this answer guys. This is a possible approach. If do not perfectly fit the needs of the question owner still gives us a valuable input. If there is an actual error in it, pls comment your suggestion to fix it, do not downvote.
|
0

You can checkout react-draggable library, just wrap component in Draggable component

Install npm i react-draggable

Import import Draggable from 'react-draggable'

Usage:

<Draggable 
   axis="both"
   cancel="input, textarea, span, label"
>
  <div style={myStyle}>test</div>
</Draggable>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.