How You Can Use Drag and Drop in Your React App

Looking at the title we can assume that, today we are going to learn an interesting lession like drag & drop. Well, as its name says, drag and drop in an application or website involves selecting a text, box, image, or file, dragging it, and placing it in the desired section or location.


In order to enable this feature in our React app, we just need to follow a few simple steps. So let's get started along-

Table of Contents

  1. Create a list
  2. Add draggable attribute 
  3. Locate the item to be dragged
  4. Track items being dragged
  5. Rearrange the list

Create a list

Let's define our list with some items

const [list, setList] = useState(['Item 1','Item 2','Item 3','Item 4','Item 5','Item 6']);

Add draggable attribute

Now we will add draggable attribute to our list item with iterating over them-

import React, { useState, useRef } from 'react';
import './App.css';
 
const App = () => {
 
  const [list, setList] = useState(['Item 1','Item 2','Item 3','Item 4','Item 5','Item 6']);
 
  return (
    <>
    {
    list&&
    list.map((item, index) => (
      <div style={{backgroundColor:'lightblue', margin:'20px 25%', textAlign:'center', fontSize:'40px'}}
        key={index} draggable
>
          {item}
      </div>
      ))}
    </>
  );
};
export default App;

Locate the Item to be dragged

To hold the item being dragged and enable dragging and dropping of all items in a list, we will utilize the useRef hook to store the item's location and the onDragStart function.

import React, { useState, useRef } from 'react';
import './App.css';
 
const App = () => {
  
  const dragItem = useRef();
  const [list, setList] = useState(['Item 1','Item 2','Item 3','Item 4','Item 5','Item 6']);
 
  const dragStart = (e, position) => {
    dragItem.current = position; 
  };
 
  return (
    <>
    {
    list&&
    list.map((item, index) => (
      <div style={{backgroundColor:'lightblue', margin:'20px 25%', textAlign:'center', fontSize:'40px'}}
        onDragStart={(e) => dragStart(e, index)}
        key={index}
        draggable>
          {item}
      </div>
      ))}
    </>
  );
};
export default App;

Track items being dragged

In this stage, the objective is to determine the underlying element on which the dragged element is floating. This can be accomplished using useRef, which enables us to modify links as the element moves over another element. Another way to accomplish this is by utilizing the onDragEnter event listener.


import React, { useState, useRef } from 'react';
import './App.css';
 
const App = () => {
  
  const dragItem = useRef();
  const dragOverItem = useRef();
  const [list, setList] = useState(['Item 1','Item 2','Item 3','Item 4','Item 5','Item 6']);
 
  const dragStart = (e, position) => {
    dragItem.current = position; 
  };
 
  const dragEnter = (e, position) => {
    dragOverItem.current = position; 
  };
 
  return (
    <>
    {
    list&&
    list.map((item, index) => (
      <div style={{backgroundColor:'lightblue', margin:'20px 25%', textAlign:'center', fontSize:'40px'}}
        onDragStart={(e) => dragStart(e, index)}
        onDragEnter={(e) => dragEnter(e, index)}
        key={index}
        draggable>
          {item}
      </div>
      ))}
    </>
  );
};
export default App;

Rearrange the list

So, now the final work to be done is  rearranging the list when we manage to place the element we dragged on top of another element or in another place.

import React, { useState, useRef } from 'react';
import './App.css';
 
const App = () => {
  
  const dragItem = useRef();
  const dragOverItem = useRef();
  const [list, setList] = useState(['Item 1','Item 2','Item 3','Item 4','Item 5','Item 6']);
 
  const dragStart = (e, position) => {
    dragItem.current = position;
  };
 
  const dragEnter = (e, position) => {
    dragOverItem.current = position;
  };
 
  const drop = (e) => {
    const copyListItems = [...list];
    const dragItemContent = copyListItems[dragItem.current];
    copyListItems.splice(dragItem.current, 1);
    copyListItems.splice(dragOverItem.current, 0, dragItemContent);
    dragItem.current = null;
    dragOverItem.current = null;
    setList(copyListItems);
  };
 
  return (
    <>
    {
    list&&
    list.map((item, index) => (
      <div style={{backgroundColor:'lightblue', margin:'20px 25%', textAlign:'center', fontSize:'40px'}}
        onDragStart={(e) => dragStart(e, index)}
        onDragEnter={(e) => dragEnter(e, index)}
        onDragEnd={drop}
        key={index}
        draggable>
          {item}
      </div>
      ))}
    </>
  );
};
export default App;

Thanks for reading. Hope you find this article helpful.