What will be covered in this article:
- 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):
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…
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
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.
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
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
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 2in our case);
- Step 3 and 4: Add
returnItemsForColumnfunction 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:
Tasks array with our tasks objects:
Now, we can modify our App component:
- Step 1: Refactor old items to imported
- Steps 2, 3, and 4: Refactor our previous code with the use of new
- Steps 5: Add new
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.
Now, let’s check what we’ve accomplished :
As you probably guessed, we can move tasks from
Do it column to
Awaiting review, or
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
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 (
canDropfunction will override
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: