Drag and Drop starter project with ReactJS - Part 2
Tags: react, javascript, draganddrop, starterproject
Published: 2021-04-29 11:50:46

## _Hello fellow developers,_

This post is a continuation of the series _Drag and Drop Starter Project with ReactJS_. In this series, I will walk you people through building a starter project for drag and drop feature in ReactJS without using any external library. Drag and drop features are used in a lot of projects, such as site builders, drawing apps, applications where user can customize their screen, and many more. 

&nbsp;
In part one, we built
- Drag and drop UI components
- Custom styled our components
- A basic drag and drop feature

_[You can re-visit Part One of the series here](https://dev.to/vedant1202/drag-and-drop-starter-project-with-reactjs-3670)_
&nbsp;
By the end of part 1, you should be having the following screen,
![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6b1gx3wfmvnjq6s894pb.png)
&nbsp;
In this part we would be,
1. Making components redraggable
2. Adding feature to remove elements

&nbsp;
Let's get onto it!
&nbsp;
### 1. Making components redraggable
&nbsp;
To make the components redraggable, we need to know the `id` of the component being dragged. For this, we need to update our `dragStart` class method in the App component.
```jsx
//App.js
...
  dragStart = (ev, type, redrag=false, elementId=null) => {
    ev.dataTransfer.setData("type", type);
    if (redrag) {
      ev.dataTransfer.setData("elementId", elementId);
    }
  }
...
```
This would set the current dragging element's ID in the `dataTransfer` attribute of the drag event.
&nbsp;
Now we need to make two changes in the `getElementList` utility function we created earlier. We need to pass this function as a parameter, and need to update the HTML to make them draggable and to accommodate this updated function.
```jsx
//utility.js
const getElementList = (elementData, dragStartHandler) => {
  const elements = [];

  Object.keys(elementData).forEach(key => {
    let { type, left, top } = elementData[key];

    switch (type) {
      case 'blue':
        elements.push(
          <div
            className="component blue"
            key={key}
            style={{
              position: 'absolute',
              left: left + 'px',
              top: top + 'px',
              zIndex: 100,
            }}
            draggable={true}
            onDragStart={(ev) => { dragStartHandler(ev, type, true, key); }}
          >
            Blue Component
        </div>
        );
        break;

      case 'green':
        elements.push(
          <div
            className="component green"
            key={key}
            style={{
              position: 'absolute',
              left: left + 'px',
              top: top + 'px',
            }}
            draggable={true}
            onDragStart={(ev) => { dragStartHandler(ev, type, true, key); }}
          >
            Green Component
        </div>
        );
        break;

      case 'purple':
        elements.push(
          <div
            className="component purple"
            key={key}
            style={{
              position: 'absolute',
              left: left + 'px',
              top: top + 'px',
            }}
            draggable={true}
            onDragStart={(ev) => { dragStartHandler(ev, type, true, key); }}
          >
            Purple Component
        </div>
        );
        break;

      default:
        break;
    }
  });

  return elements;
}

export { getElementList };
```
&nbsp;
Now, finally, we need to update the drop class method in App component. We need to capture the element's ID if it exists, and then update the "X" and "Y" co-ordinates of that element.
```jsx
//App.js
...
  drop = (ev) => {
    ev.preventDefault();
    const type = ev.dataTransfer.getData("type");
    const { elementData } = this.state;
    let { nextElementId } = this.state;
    const newElementData = {
      type,
      left: ev.clientX,
      top: ev.clientY,
    }

    let elementId = ev.dataTransfer.getData("elementId");
    if (elementId) {                 // check if element is redragged and the ID exists in dataTransfer
      elementId = parseInt(elementId);
      elementData[elementId] = {
        ...elementData[elementId],
        left: ev.clientX,
        top: ev.clientY,
      }
      parseInt(ev.dataTransfer.getData("elementId"))
    } else {
      elementData[nextElementId] = newElementData;
      nextElementId = nextElementId + 1;
    }

    ev.dataTransfer.clearData();

    this.setState({
      elementData,
      nextElementId,
    });
  }

...
```
&nbsp;
When you run this and visit the browser, you should be able to re-drag the components
![re-drag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vn9lnrs0pjn3bb5zheag.gif)
&nbsp;
We now have added the ability to re-drag and re-arrange the components in our app.

&nbsp;
### 2. Remove or delete the components
&nbsp;
We can add the feature to remove the components from the Drop Area when they are dragged outside of it. This is a relatively simple feature since most of the things are already setup. 
&nbsp;
First, we create a new class method in the App component, named `dropOutside`, which would handle removing the element's data from the state. This is done by retrieving the dragged element's ID and removing that entry from the `elementData` in the App component's state.
```jsx
//App.js
...
  dropOutside = (ev) => {
    const { elementData } = this.state;
    let elementId = ev.dataTransfer.getData("elementId");
    if (elementId && elementData[elementId]) {
      delete elementData[elementId];
    }

    ev.dataTransfer.clearData();

    this.setState({
      elementData,
    });
  }
...
```
&nbsp;
Now we add this method to the `onDrop` attribute of the Components List div (the left side div).
```jsx
//App.js
...

        <div className="components-list" onDrop={this.dropOutside} onDragOver={this.dragOver}>
          
...
```
&nbsp;
And we're done with it. When the page updates in the browser, you should be able to delete the elements from the Drop Area when you drag them outside of it.
![remove-elements](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/079p95zlaqo3qh0927ri.gif)
 
&nbsp;
Alright then, that's it from me for now hope it was helpful. Feel free to drop any questions in the comments section!
&nbsp;
Code Hosted at {% github Vedant1202/Drag-and-Drop-Starter- no-readme %}
&nbsp;
Demo hosted at [Drag and Drop Starter Demo](http://Vedant1202.github.io/Drag-and-Drop-Starter-)
&nbsp;
You can follow me on my [Dev.to @vedant1202] 
and on my [Github@Vedant1202](https://github.com/Vedant1202)
&nbsp;
_Peace and stay safe ✌️_

&nbsp;
### Footnotes
&nbsp;
1. Cover image taken from Photo by <a href="https://unsplash.com/@mimithian?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Mimi Thian</a> on <a href="https://unsplash.com/s/photos/laptop-trackpad?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>

2. References from [Mozilla Developer Network Web Documentation](https://developer.mozilla.org/en-US/)