React DnD in Examples

Artem Diashkin
Oct 7, 2020 · 8 min read
Image for post
Image for post

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):

Image for post
Image for post

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):

Image for post
Image for post

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…

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

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:

Wrapping component and adding useDrag hook 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).

Image for post
Image for post

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

Image for post
Image for post

Let’s take a look at the results:

Image for post
Image for post

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:

Image for post
Image for post

Now, let’s check it out:

Image for post
Image for post

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:

Image for post
Image for post

Next, we will modify App component.

Image for post
Image for post

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.

Image for post
Image for post

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.

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

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 or Column 2 in our case);
  • Step 3 and 4: Add returnItemsForColumn function into Columns components
Image for post
Image for post

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.

Image for post
Image for post

Let’s check it out:

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

Step 3 code was copied from the React DnD docs example:

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

Image for post
Image for post

Mobile version of drag and drop

Note, that our previous app version will not correctly work for mobile devices:

Image for post
Image for post

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:

Image for post
Image for post

Let’s test it:

Image for post
Image for post

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:

Image for post
Image for post

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 and Done columns.
Image for post
Image for post

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.

Image for post
Image for post

Gists of an App component, just in case, and updated styles.

Now, let’s check what we’ve accomplished :

Image for post
Image for post

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:

Image for post
Image for post

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

Image for post
Image for post

Finally, we need to modify “droppable” component (Column component).

NOTE: defining canDrop function will override monitor.canDrop() function.

At Step 2 we are describing “if” conditions, that are defining can user drop current item onto current column or not.

Image for post
Image for post

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

Image for post
Image for post

You can check code implementation on Github or in Codesandbox:

The Startup

Medium's largest active publication, followed by +771K people. Follow to join our community.

Artem Diashkin

Written by

Java, Spring, Node.js, AdonisJs, React.js and Flutter developer

The Startup

Medium's largest active publication, followed by +771K people. Follow to join our community.

Artem Diashkin

Written by

Java, Spring, Node.js, AdonisJs, React.js and Flutter developer

The Startup

Medium's largest active publication, followed by +771K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store