最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to drag and drop content with react? - Stack Overflow

programmeradmin2浏览0评论

I need to render the content from this div:

  <div class="col-sm-4">
                  <ul class="list-group">
                  <li class="list-group-item"><a href="#">File Reader</a></li>
                  <li class="list-group-item" ><a href="#">File Move</a></li>
                  <li class="list-group-item" ><a href="#">Data Base</a></li>
                  <li class="list-group-item"><a href="#">SAP R3</a></li>
                  <li class="list-group-item"><a href="#">FTP</a></li>
                  <li class="list-group-item"><a href="#">SOAP</a></li>
                  <li class="list-group-item"><a href="#">Rest</a></li>
                  <li class="list-group-item"><a href="#">Merge</a></li>
                  <li class="list-group-item"><a href="#">Filter</a></li>
                  <li class="list-group-item"><a href="#">Transform</a></li>
              </ul>
              </div>

Into a Drag and Drop, i tried a lot of examples but nothing seems to work.

Here is my code right now :

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import { ItemTypes } from './Constants';
import styles2 from './Styles.css'
import { render } from 'react-dom';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

const styles = {
  fontFamily: 'sans-serif',
  textAlign: 'center', 
};



function collect(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging()
  };
}
function _(id){
   return document.getElementById(id);  
}
var droppedIn = false;
function drag_start(event) {
    _('app_status').innerHTML = "Dragging the "+event.target.getAttribute('id');
    event.dataTransfer.dropEffect = "move";
    event.dataTransfer.setData("text", event.target.getAttribute('id') );
}
function drag_enter(event) {
    _('app_status').innerHTML = "You are dragging over the "+event.target.getAttribute('id');
}
function drag_leave(event) {
    _('app_status').innerHTML = "You left the "+event.target.getAttribute('id');
}
function drag_drop(event) {
    event.preventDefault(); /* Prevent undesirable default behavior while dropping */
    var elem_id = event.dataTransfer.getData("text");
    event.target.appendChild( _(elem_id) );
    _('app_status').innerHTML = "Dropped "+elem_id+" into the "+event.target.getAttribute('id');
    _(elem_id).removeAttribute("draggable");
    _(elem_id).style.cursor = "default";
    droppedIn = true;
}
function drag_end(event) {
    if(droppedIn == false){
        _('app_status').innerHTML = "You let the "+event.target.getAttribute('id')+" go.";
    }
  droppedIn = false;
}
function readDropZone(){
    for(var i=0; i < _("drop_zone").children.length; i++){
        alert(_("drop_zone").children[i].id+" is in the drop zone");
    }
    /* Run Ajax request to pass any data to your server */
}
const propTypes = {
  text: PropTypes.string.isRequired,

  // Injected by React DnD:
  isDragging: PropTypes.bool.isRequired,
  connectDragSource: PropTypes.func.isRequired
};

class BasicForm extends React.Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }



   render() {
    return (

      <div style={styles}>
       <form onSubmit={this.handleSubmit}>


        <div class="container">
            <div class="row">
             <div class="col-sm-4">
                      <ul class="list-group">
                      <li class="list-group-item"><a href="#">File Reader</a></li>
                      <li class="list-group-item" ><a href="#">File Move</a></li>
                      <li class="list-group-item" ><a href="#">Data Base</a></li>
                      <li class="list-group-item"><a href="#">SAP R3</a></li>
                      <li class="list-group-item"><a href="#">FTP</a></li>
                      <li class="list-group-item"><a href="#">SOAP</a></li>
                      <li class="list-group-item"><a href="#">Rest</a></li>
                      <li class="list-group-item"><a href="#">Merge</a></li>
                      <li class="list-group-item"><a href="#">Filter</a></li>
                      <li class="list-group-item"><a href="#">Transform</a></li>
                  </ul>
                  </div>
              <h2 id="app_status">App status...</h2>
              <h1>Drop Zone</h1>
              <div id="drop_zone"  onDragEnter="drag_enter(event)" onDrop="drag_drop(event)" onDragOver="return false" onDragLeave="drag_leave(event)" className={styles2.drop_zone} ></div>

              </div>
          </div>
          <input type="submit" value="Submit" />
      </form>  
       </div>
    );
  }

}export default DragDropContext(HTML5Backend)(BasicForm);

On my console i get this error : Expected onDragEnter listener to be a function, instead got a value of string type. What i'm doing wrong? PS: I'm new with React, i tried so many examples, so the code is a little bit big.

I need to render the content from this div:

  <div class="col-sm-4">
                  <ul class="list-group">
                  <li class="list-group-item"><a href="#">File Reader</a></li>
                  <li class="list-group-item" ><a href="#">File Move</a></li>
                  <li class="list-group-item" ><a href="#">Data Base</a></li>
                  <li class="list-group-item"><a href="#">SAP R3</a></li>
                  <li class="list-group-item"><a href="#">FTP</a></li>
                  <li class="list-group-item"><a href="#">SOAP</a></li>
                  <li class="list-group-item"><a href="#">Rest</a></li>
                  <li class="list-group-item"><a href="#">Merge</a></li>
                  <li class="list-group-item"><a href="#">Filter</a></li>
                  <li class="list-group-item"><a href="#">Transform</a></li>
              </ul>
              </div>

Into a Drag and Drop, i tried a lot of examples but nothing seems to work.

Here is my code right now :

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { DragSource } from 'react-dnd';
import { ItemTypes } from './Constants';
import styles2 from './Styles.css'
import { render } from 'react-dom';
import {DragDropContext} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';

const styles = {
  fontFamily: 'sans-serif',
  textAlign: 'center', 
};



function collect(connect, monitor) {
  return {
    connectDragSource: connect.dragSource(),
    isDragging: monitor.isDragging()
  };
}
function _(id){
   return document.getElementById(id);  
}
var droppedIn = false;
function drag_start(event) {
    _('app_status').innerHTML = "Dragging the "+event.target.getAttribute('id');
    event.dataTransfer.dropEffect = "move";
    event.dataTransfer.setData("text", event.target.getAttribute('id') );
}
function drag_enter(event) {
    _('app_status').innerHTML = "You are dragging over the "+event.target.getAttribute('id');
}
function drag_leave(event) {
    _('app_status').innerHTML = "You left the "+event.target.getAttribute('id');
}
function drag_drop(event) {
    event.preventDefault(); /* Prevent undesirable default behavior while dropping */
    var elem_id = event.dataTransfer.getData("text");
    event.target.appendChild( _(elem_id) );
    _('app_status').innerHTML = "Dropped "+elem_id+" into the "+event.target.getAttribute('id');
    _(elem_id).removeAttribute("draggable");
    _(elem_id).style.cursor = "default";
    droppedIn = true;
}
function drag_end(event) {
    if(droppedIn == false){
        _('app_status').innerHTML = "You let the "+event.target.getAttribute('id')+" go.";
    }
  droppedIn = false;
}
function readDropZone(){
    for(var i=0; i < _("drop_zone").children.length; i++){
        alert(_("drop_zone").children[i].id+" is in the drop zone");
    }
    /* Run Ajax request to pass any data to your server */
}
const propTypes = {
  text: PropTypes.string.isRequired,

  // Injected by React DnD:
  isDragging: PropTypes.bool.isRequired,
  connectDragSource: PropTypes.func.isRequired
};

class BasicForm extends React.Component {

  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }



   render() {
    return (

      <div style={styles}>
       <form onSubmit={this.handleSubmit}>


        <div class="container">
            <div class="row">
             <div class="col-sm-4">
                      <ul class="list-group">
                      <li class="list-group-item"><a href="#">File Reader</a></li>
                      <li class="list-group-item" ><a href="#">File Move</a></li>
                      <li class="list-group-item" ><a href="#">Data Base</a></li>
                      <li class="list-group-item"><a href="#">SAP R3</a></li>
                      <li class="list-group-item"><a href="#">FTP</a></li>
                      <li class="list-group-item"><a href="#">SOAP</a></li>
                      <li class="list-group-item"><a href="#">Rest</a></li>
                      <li class="list-group-item"><a href="#">Merge</a></li>
                      <li class="list-group-item"><a href="#">Filter</a></li>
                      <li class="list-group-item"><a href="#">Transform</a></li>
                  </ul>
                  </div>
              <h2 id="app_status">App status...</h2>
              <h1>Drop Zone</h1>
              <div id="drop_zone"  onDragEnter="drag_enter(event)" onDrop="drag_drop(event)" onDragOver="return false" onDragLeave="drag_leave(event)" className={styles2.drop_zone} ></div>

              </div>
          </div>
          <input type="submit" value="Submit" />
      </form>  
       </div>
    );
  }

}export default DragDropContext(HTML5Backend)(BasicForm);

On my console i get this error : Expected onDragEnter listener to be a function, instead got a value of string type. What i'm doing wrong? PS: I'm new with React, i tried so many examples, so the code is a little bit big.

Share Improve this question asked Jan 23, 2018 at 13:22 Lucio ZenirLucio Zenir 3852 gold badges8 silver badges19 bronze badges 8
  • 1) react-sortable-hoc 2) react-beautiful-dnd 3) react-dnd – Daniel Khoroshko Commented Jan 24, 2018 at 1:24
  • 1 Already tried the 3, none worked, i want to know how to do it, i know the libs already, in this case i'm using react-dnd – Lucio Zenir Commented Jan 24, 2018 at 10:07
  • Hi! In this particular example the error is that you are providing (just as it says) strings instead of functions as event handlers. To fix this error you need to change onDrag...="..." into onDrag..={() => ...} I am afraid it won't really help because, I've just checked the code, it's done in a none react way pletely. In react you don't fiddle with dom objects manually, also you drag items/drag containers should we properly wrapped with react-dnd functions, etc.. Probably you could check the tutorial and copy the logic from there. – Daniel Khoroshko Commented Jan 24, 2018 at 15:22
  • Frankly speaking react-dnd is more plicated to with as it requires more manual setup and doesn't provide animations out of the box, which you probably would like to have – Daniel Khoroshko Commented Jan 24, 2018 at 15:23
  • I'm trying to make without a lib, but i cant pass the OnDragOver = false, do u know how to do it? – Lucio Zenir Commented Jan 24, 2018 at 17:33
 |  Show 3 more ments

2 Answers 2

Reset to default 4

This is a basic drag and drop example for list in react. Does not handle the dropping yet, only the dragging and the scroll.

const getWindowScroll = () => {
    const doc = document.documentElement;
    return (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
  }

class App extends React.Component {
  setElemRef = ref => {
    this.elemRef = ref;
  }
  
  initialiseDrag = event => {
    const {target, clientY} = event;
    const { offsetTop } = target;
    const { top } = this.elemRef.getBoundingClientRect();
    this.dragStartTop = top - offsetTop;
    this.dragStartY = clientY;
    window.addEventListener('mousemove', this.startDragging, false);
    window.addEventListener('mouseup', this.stopDragging, false);
  }
  
  startDragging = ({ clientY }) => { 
    let newTop = this.dragStartTop + clientY - this.dragStartY + getWindowScroll();
    if (newTop < 0) newTop = 0;
    this.elemRef.style.transform = `translateY(${newTop}px)`;
    this.scrollIfElementBottom(newTop);
  }

  stopDragging = () => {
    window.removeEventListener('mousemove', this.startDragging, false);
    window.removeEventListener('mouseup', this.stopDragging, false);
  }  
  
  scrollIfElementBottom = newTop => {
    if (newTop > 30) {
      window.scroll({
        top: newTop,
        behavior: 'smooth'
      });    
    }
    if (newTop < 30) {
      window.scroll({
        top: 0,
        behavior: 'smooth'
      });      
    }
  };
  
  render(){
    return (
      <React.Fragment>
        <div onMouseDown={this.initialiseDrag} ref={this.setElemRef}>DragMe</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
        <div>List elem</div>
      </React.Fragment>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
#root div {
  background: gray;
  padding: 20px;
  margin: 10px;
  user-select: none;
  cursor: pointer;
  border: 1px solid lightgray;
}
<script src="https://cdnjs.cloudflare./ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

https://github./peterh32/react-drag-drop-container is a pretty simple library. If I understand what you are trying to do (drag LIs into the "Drop Zone"), you'd do something like this for each LI:

<DragDropContainer onDrop={...} onDragStart={...} ...etc. >
  <li class="list-group-item"><a href="#">File Reader</a></li>
</DragDropContainer>

...and then for your drop zone:

<DropTarget onHit={...} onDragEnter={...} ...etc.>
  <div id="drop-target">...</div>
</DropTarget>

The events go right into the containers as you can see. It handles mouse and touch interfaces and also does stuff like scrolling when you get to the edge of the screen (so you can drag to destinations that are initially offscreen).

发布评论

评论列表(0)

  1. 暂无评论