Learn More

Try out the world’s first micro-repo!

Learn More

How to Implement Drag and Drop in React

How to Implement Drag and Drop in React

The front-end application world is an ocean of infinite possibilities for building your application. You can have your users interact with an application in so many ways!

However, some recognizable patterns are used in most applications. For example, drag and drop functionality is one frequently used method. Knowing this can help us to make our React applications more user-friendly.

When to Use Drag and Drop

These are common use cases of drag-and-drop functionality:

  • Reordering items in a list
  • Creating a file dropper
  • Creating something like a Trello board
  • Moving items between lists

Therefore, you should have a good working knowledge of how to build a drag-and-drop functionality in your application.

Today, we’ll cover this important skill. We’ll build a drag-and-drop functionality in our application using React Beautiful DnD. We’ll also discuss troubleshooting with the library.

What Is React Beautiful DnD?

React Beautiful DnD is a library that provides the tools to build drag-and-drop functionality into your application. It is a powerful library that provides you flexibility, and offers many features.

Why Use React Beautiful DnD?

There are many drag-and-drop libraries available on the market. However, we’ll use React Beautiful DnD because it’s simple and easy to use.

React Beautiful DnD is a very lightweight library, and is straightforward to implement in your application. It’s also very customizable, so you can adapt it to your needs.

Here are some other options that you can check out as well:

  • react-dnd: This is very popular, but it’s a bit complex to use.
  • @dnd-kit/core: This is a very lightweight library that is not as customizable as React Beautiful DnD.

What Are We Going to Build?

Now, we’ll build a simple drag-and-drop functionality in our application. We’ll have a list of items that we can drag and drop to reorder.

The final product will look something like this.

Prerequisites

You’ll need a basic knowledge of React, and that’s it! Let's get started.

Set Up the Application

First, create a boilerplate ReactJS application:

npx create-react-app drag-n-drop-demo

Then, install the dependencies:

npm install react-beautiful-dnd

1. Create a Simple Task List

Let's first make a simple list of tasks as a starting point:

const initialTasks = [
{
id: 1,
title: "Task 1",
},
{
id: 2,
title: "Task 2",
},
{
id: 3,
title: "Task 3",
},
];

Save this code

2. Create the Context

The first step in using drag and drop functionality is to declare a particular area on the screen as droppable.

The way we do this is by creating a context. We will use this context to wrap the area on the screen where we want the drag-and-drop functionality:

<DragDropContext onDragEnd={onDragEnd}>
All drag-and-drop functionality happens inside this context
</DragDropContext>

You’ll notice a special function called onDragEnd passed into the context. We will use this function to update the state of our application.

For now, let’s use the following code:

const onDragEnd = (result) => {
console.log(result);
};

Basically, this function will be called after a user finishes a drag-and-drop operation.

3. Create the Droppable Area

Let's create a component that will be used to wrap the area on the screen that will be droppable:

<Droppable droppableId="tasks">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{ Your draggable items go here }
{provided. placeholder} // This is a placeholder that will be used to show the space where the item will be dropped
</div>
)}
</Droppable>

Save this code

The droppableId is a unique identifier for the droppable area. This is used to identify the area when the drag-and-drop operation is completed.

The provided object contains two properties.

The innerRef refers to the DOM element that wraps the droppable area. The droppableProps is a set of props that will be applied to the DOM element.

4. Create the Draggable Items

Now, let's go over the task items individually and make them draggable:

{
tasks.map((task, index) => (
<Draggable key={task.id} draggableId={task.id.toString()} index={index}>
{(provided) => (
<div
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<div>{task.title}</div>
</div>
)}
</Draggable>
));
}

Save this code

The Draggable component takes in two props. The draggableId is a unique identifier for the draggable item, and the index is the position of the item in the list.

The provided object contains three properties. The draggableProps is a set of props that will be applied to the DOM element. The dragHandleProps is a set of props applied to the DOM element used to drag the item. The innerRef refers to the DOM element that wraps the draggable item.

Now, you should have a working drag-and-drop functionality. However, you’ll notice that the items will return to their original position after updating them.

Let's solve that issue!

5. Update the State

The above issue occurs because the application's state is not updated when the drag-and-drop operation is completed.

Let's update the application's state when the drag-and-drop operation is completed:

const onDragEnd = (result) => {
if (!result.destination) return;

const items = Array.from(tasks);
const [reorderedItem] = items.splice(result.source.index, 1);
items.splice(result.destination.index, 0, reorderedItem);

setTasks(items);
};

Save this code

The result object contains the source and destination properties. The source property includes the index and droppableId of the dragged item.

The destination property contains the index and droppableId of the dropped item.

6. Complete Code

import React, { useState } from "react";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";

const initialTasks = [
{
id: 1,
title: "Task 1",
},
{
id: 2,
title: "Task 2",
},
{
id: 3,
title: "Task 3",
},
];

function App() {
const [tasks, setTasks] = useState(initialTasks);

const onDragEnd = (result) => {
if (!result.destination) return;

const items = Array.from(tasks);
const [reorderedItem] = items.splice(result.source.index, 1);
items.splice(result.destination.index, 0, reorderedItem);

setTasks(items);
};

return (
<div className="App">
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="tasks">
{(provided) => (
<div ref={provided.innerRef} {...provided.droppableProps}>
{tasks.map((task, index) => (
<Draggable
key={task.id}
draggableId={task.id.toString()}
index={index}
>
{(provided) => (
<div
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
>
<div>{task.title}</div>
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</DragDropContext>
</div>
);
}

export default App;

Save this code

Common Issues

1. The draggable item is not moving.

Sometimes, you’ll notice that the items are not moving. If you open the console, you’ll see errors like the following:

Unable to find draggable with id: 1

This is a known issue and usually happens due to the use of React.StrictMode on your index.js file.

To fix this issue, you have to remove the React.StrictMode.

Instead of this:

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);

Use this:

ReactDOM.render(<App />, document.getElementById("root"));

This should solve the issue.

2. The draggable item is not moving smoothly.

If you notice that the draggable item is not moving smoothly, you can try to add the following CSS to your application:

.react-beautiful-dnd-draggable {
transition: transform 0.2s;
}

3. The draggable item is not moving to the correct position.

This is usually caused by the draggable item not having a height designated. You can fix this by adding a height value to the draggable object.

Github Repo:

https://github.com/Mohammad-Faisal/react-drag-n-drop-demo

References

Interested in becoming a Pieces Content Partner?

Learn More

Get our latest blog posts and product updates by signing up for our monthly newsletter! 

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Table of Contents

React

Frontend

More from Pieces