Drag and Drop Functionality in React

Joe Cha
bother7-blog
Published in
3 min readSep 27, 2017

TLDR: Here’s the demo, drag and drop libraries aren’t necessary. Scroll down for code

Now that we are in React, I thought it would be interesting to move div containers around and create a dynamic website layout. Just being able to move containers around turned out to be much more difficult than I thought, but it was a good exercise, and it makes sense to implement customizable containers within a React/JS environment.

Drag and drop functionality was introduced in HTML 5. Follow this link for documentation. In terms of React, there are several libraries that add drag and drop functionality to css components. I wanted to write the code myself, but libraries like react-dnd, draggable, and beautiful-dnd are useful if you want want to immediately add functionality to your code.

Here is the demo. Div containers can move around and swap places. I was originally grabbing coordinates and trying to drop containers, but adding snapping movement meant I could clean up the code and just work with dropping targets in the correct place.

There are several event listeners that I used that are specifically part of drag and drop.

<div className={} id={} draggable="true" onDragStart={} onDrop={} onDragOver={event.preventDefault()} onDragEnd={}>

draggable=”true” is very important, and had to be written directly into the jsx div here and couldn’t be part of the stylesheet. I believe this is an issue with react and HTML 5. The dragging action won’t occur without adding this property.

Four more event listeners were added as part of drag and drop functionality. onDragStart, onDrop, onDragOver, and onDragEnd.

onDragStart and onDrop are the most important for this demo, they are the start and end of the drag movement and they carry dataTransfer along with them. onDrop is useful as it is triggered only when a div is dropped on top of another div. onDragOver is added just for event.preventDefault().

It is funny that dragging has it’s own dedicated object, but its the best way to transmit data from the beginning point to the end point of a drag. The dataTransfer object is created once dragging begins. I was just storing and reading the dataTransfer object, but there are also inner functions and other parts of the dataTransfer object that I did not explore further.

These event listeners work in conjunction with event.dataTransfer for drag and drop functionality. Messages can be stored and sent in a drag through the event.dataTransfer. For the purposes of this demo, the dataTransfer stores the original div id and compares it to the drop target div id. The identities of the two div containers that are going to switch places are then sent in a callback function up to a parent. This function swaps the places of the two items in the array.

import React, { Component } from 'react';class Card extends Component {
state = {
index: this.props.index,
targetbox: null
}
cssGrid = {
1: "one",
2: "two",
3: "three",
4: "four",
5: "five",
6: "six"
}
dragEnd = (event) => {
this.setState({targetbox: null})
}
dragStart = (event) => {
event.dataTransfer.setData("text", event.target.id)
this.setState({targetbox: true})
}
drop = (event) => {
if (event.target.id) {
this.props.swap(event.dataTransfer.getData("text"), event.target.id)
event.dataTransfer.clearData()
}
}
render(){
if (this.state.targetbox === null) {
return (<div className={this.cssGrid[this.state.index]} id={this.props.title} draggable="true" onDrop={this.drop} onDragStart={this.dragStart} onDragOver={(event) => event.preventDefault()} onDragEnd={this.dragEnd} ><h3>{this.props.title}</h3><p>{this.props.details}</p></div>)
}
else {
const style = {backgroundColor: 'red'}
return (<div style={style} className={this.cssGrid[this.state.index]} id={this.props.title} draggable="true" onDrop={this.drop} onDragStart={this.dragStart} onDragOver={(event) => event.preventDefault()} onDragEnd={this.dragEnd} ></div>)
}
}
}export default Card

Future things I would like to implement is for a preview of the new div locations to occur. These functionalities and more are included in some of the libraries that I have previously mentioned.

https://github.com/bother7/my-homepage-app

--

--