React DnD in Examples

React DnD is a set of React utilities to help you build complex drag and drop interfaces . We will take a look on it’s basic capabilities with implementing our own kanban board.
What will be covered in this article:
- Prerequisites
- Installation
- Implementing draggable item
- Implementing droppable item
- Creatin kanban board
- Adding multiple draggable items
- Make items sortable in the column
- Mobile version of drag and drop
- Refactor before adding drop restrictions
- Adding drop restrictions
Before we will start our journey, let’s see what we will get at the end (gif):

Prerequisites
We will start from a simple React application created by using create-react-app
script with few changes in a project (remove some styles and code fragments):

App component consists of two column componets from/to which we will drag and drop our MovableItem:
And some not complex styles, so that our examples would look not too terrible 😉:
And our application would look like this. Very simple…

Installation
To use react-dnd
library we will need to add react-dnd
and react-dnd-html5-backend
npm packages to our project:
yarn add react-dnd react-dnd-html5-backend// ORnpm install react-dnd react-dnd-html5-backend
react-dnd-html5-backed
uses the HTML5 drag and drop API under the hood.
Now we can start implementing our Drag and Drop functionality:
Implementing draggable item
Note: After code snippet screenshots, I will add gists, so you could easily copy-paste it in your code, so no worries
At first, we will need to wrap our components that are taking part in drag and drop with DndProvider
.

Next, we will add useDrag
hook to our “draggable” component:

Some values are irrelevant for now, like item
properties, no worries, I’ll explain about them a little bit later.
Current app’s code snippet:
After updating our code, we will notice some changes in our app’s behavior → now we can drag our MovableItem (without any additional functionality).

Implementing droppable item
To make our MovableItem
“droppable” to a specific region (Second component in our case) we will need to add useDrop
hook, with some logic.
NOTE: I am deliberately specified accept type as
Not existing type

Let’s take a look at the results:

As you can see — nothing happens. canDrop
and isOver
returned values only on the component’s first renders, and that’s all. Why is that?
The reason, as you might’ve guessed, is in accept type
. When you got a lot of draggable objects, which you can drag from one to another — you need to specify an acceptable type, on which droppable component will react.
Let’s make it happen:

Now, let’s check it out:

Creatin kanban board
Before we will create kanban board we need to make a few changes to our code, not complex, believe me 😉.
First, we need to rename our FirstColumn
and remove SecondColumn
component:

Next, we will modify App component.

The reason for the refactor is that we need our MovableComponent
not to be hardcoded in the FirstComponent
, but to be more flexible, so that we can decide when to place it.
Now we can add some logic for moving from one column to another. It will be done by using a simple boolean
variable.

Next, we can remove unnecessary logic in the “Droppable” column. All we will need is a “droppable” name (Column 1
or Column 2
in our case), which is declared at code line 41.

Next, we need to add end logic for the “droppable” item, in other words — what should be done when a user releases button after drag.

Let’s take a look at what we’ve accomplished so far:

Here is the code gist for this example.
Adding multiple draggable items
But how to handle multiple items in a column? Let’s find out.
- Step 1: Create multiple items;
- Step 2: Create a function that will return MovableItem that has a column name equal to our needs (
Column 1
orColumn 2
in our case); - Step 3 and 4: Add
returnItemsForColumn
function into Columns components

Next, we will need to modify MovableItem
, so that when a user “drops” item, we could define where exactly. As you remember getDropResult()
will return “droppable” object properties on which user “dropped” “draggable” item.
At Step 2 we are changing the item’s column property to the current “droppable” column name.

Let’s check it out:

I think that now you got the main idea behind the react-dnd
library. But we can make it more interesting.
Make items sortable in the column
For this example, I’ve used an example by this link, but without any third-party libraries, like immutability-helper
npm package, without callbacks, plus it is much interesting to add it to our app with additional functionality like columns, and check how they will work together.
At first, we will need to define a moveCardHandler
, that will handle changing item position in our array.

Next, we will need to add useRef
implementation instead of an old one.

Step 3 code was copied from the React DnD docs example:
Let’s take a look at what we’ve accomplished:

Mobile version of drag and drop
Note, that our previous app version will not correctly work for mobile devices:

To solve this issue we will need to add react-dnd-touch-backend
npm package to our project:
yarn add react-dnd-touch-backend// ORnpm install react-dnd-touch-backend --save
After that, we will need to modify our App component:

Let’s test it:

Refactor before adding drop restrictions
I think that we can finally take a closer look at additional React DnD properties that can allow us to add some restrictions to our “draggable” and “droppable” items.
First, we will need to update some of our code fragments, so that our applications would look like this:

First, let’s create constant with Column names
in a separate file:
And Tasks
array with our tasks objects:
Now, we can modify our App component:
- Step 1: Refactor old items to imported
tasks
; - Steps 2, 3, and 4: Refactor our previous code with the use of new
COLUMN_NAMES
; - Steps 5: Add new
Awaiting review
andDone
columns.

And finally, we will need to update our previous logic for setting a new task’s column name, when a user “drops” and item to the specific column.

Gists of an App component, just in case, and updated styles.
Now, let’s check what we’ve accomplished :

As you probably guessed, we can move tasks from Do it
column to Awaiting review
, or Done
.
Let’s add some restrictions to our kanban board.
Adding drop restrictions
After adding additional columns into our app we can add restrictions logic.
To determine to which column item currently belongs, we need to pass current column name
prop to the MovableItem
component:

Next, we need to add currentColumnName
to the item properties in line 65, so we can get in “droppable” component:

Finally, we need to modify “droppable” component (Column
component).
NOTE: defining
canDrop
function will overridemonitor.canDrop()
function.
At Step 2 we are describing “if” conditions, that are defining can user drop current item onto current column or not.

Let’s take a look at what we’ve accomplished (gif):

You can check code implementation on Github or in Codesandbox: