Skip to content

Tag: drag & drop reactjs

Drag & drop feature with React Beautiful DND library + Video

If you ever think about making your web application more interactive or managing data in your app, you may find the drag & drop a useful feature.

Drag & drop is a common feature of modern web applications these days, making the web pages more interactive. There are a bunch of libraries available for programmers to implement this feature in the form of React components. Among them, the react-beautiful-DND is a useful library to make a react component draggable and droppable easily, working with simple javascript concepts. In this article, we will utilize this library to create our draggable component and droppable items. So, this article is yours if you are curious about how to apply the react-beautiful- DND library to create drag & drop functionality. Also, if you find a video tutorial more engaging way to learn, this Drag & Drop Tutorial for ReactJs video on YouTube is for you. You can watch this video at the end of this post!

Ok, Let’s jump to an upper level of programming by reading this article. Consider we have a component including different items such as the following picture, and we tend to implement drag & drop features to provide users with changing the items’ order.

ReactJs Drag and Drop Using React Beautiful DND library

We have an ‘App.js’ file, including a ‘div’ for the title in which the ‘UsersPage’ component is located. ‘App.js’ is just that much simple.

<div className="App">
      <div className='title'>React Beautiful DND</div>
      <UsersPage/>
    </div>

The next step is to create ‘UsersPage’ that everything happens inside it. In this project, users’ data are saved in an array including first name, last name, and avatar of each user (You can download the array of data from https://github.com/mdeveloper20/reactReminder/tree/react-beautiful-dnd). We import data in the ‘UsersPage’ component and save them as the ‘state’ in our class extends component.

Also, in ‘render’ we have the component of Users inside <h1> </h1> that renders the users’ index, name, last name, and avatar using ‘renderUsers’ function.

import React, { Component } from 'react';
import './users.css';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
import {users} from './Data';

class UsersPage extends Component {

    state={users: users}

renderUsers = (item, index) => {
    return (
      <div>
        <div className="item">
          <div>{index + 1}</div>
          <div>
            <img src={item.avatar} alt="avatar" />
          </div>
          <div className="name">
            <div>{item.firstName}</div>
            <div>{item.lastName}</div>
          </div>
        </div>
      </div>
    );
  };

render() {
        
        return (
            <div className='container'>
                <div className='users'>
                    <h1>Users</h1>

                    <div>
                        {this.state.users.map(this.renderUsers)}
                    </div>
                </div>
                
            </div>
        );
    }
}

export default UsersPage;

Till now, we have an app that displays users’ data. Now we want to add the drag & drop feature that enables us to change the order of the displayed items. That might be exciting. So, install the library through either of the following codes:

yarn add react-beautiful-dnd

npm install react-beautiful-dnd --save

Then import the required elements from this package:

import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

In which ‘DragDropContext’ is the container of the app, ‘Droppable’ is our list container, and each item enabling us to move it is our ‘draggable’ component. Therefore, ‘DragDropContext’ is the wrapper of the component working through the ‘onDragEnd’ function, that we add it to the render. The new render code is:

render() {
      
    return (
      <DragDropContext onDragEnd={this.onDragEnd}>
        <div className="container">
          <div className="users">
            <h1>Users</h1>
             
                <div>
                  {this.state.users.map(this.renderUsers)}
                </div>
          </div>
        </div>    
      </DragDropContext>
    );
  }

And the related function that gets the new position of the element and saves it in the ‘state’ is:

onDragEnd = (result) => {
    const { destination, source, reason } = result;
    // Not a thing to do...
    if (!destination || reason === "CANCEL") {
      return;
    }

    if (
      destination.droppableId === source.droppableId &&
      destination.index === source.index
    ) {
      return;
    }

    const users = Object.assign([], this.state.users);
    const droppedUser = this.state.users[source.index];

    users.splice(source.index, 1);
    users.splice(destination.index, 0, droppedUser);
    this.setState({
      users,
    });
  };

You may wonder how this function works?! Here is the detail of this function:

The constant ‘source’ refers to the index of the item that we tend to move it, and the constant ‘destination’ is the index of the target position.

If we choose an item without specifying a destination or cancel the process, nothing should happen. So, add the first ‘if condition’ to your function to prevent any problem. Also, the second ‘if condition’ does nothing if we drag an item and drop it on its previous place, which is obvious. Then use ‘Users’ to set the state, and take advantage of Javascript function ‘splice’ to change the order of the users. If you are a beginner and you need to know how ‘splice’ serves us in this way, you can watch this video.

Ok! It’s time to implement the droppable component. As we said before, the container of items is the droppable component. So, it should be added to the render as the following code, where the ‘map’ function maps the users. We may also use ‘droppableId’ in case we have several droppable components.

render() {
    return (
      <DragDropContext onDragEnd={this.onDragEnd}>
        <div className="container">
          <div className="users">
            <h1>Users</h1>

            <Droppable droppableId="dp1">
              {(provided) => (
                <div ref={provided.innerRef} {...provided.droppableProps}>
                  {this.state.users.map(this.renderUsers)}
                  {provided.placeholder}
                </div>
              )}
            </Droppable>
          </div>
        </div>
      </DragDropContext>
    );
  }

Note: Since HTML can not pass through the droppable component, we use a function in which the ‘provided’ argument is the input.

For the next step, we need to apply ‘draggable’ for every item on the list. Thus, we wrap ‘renderUsers’ function in the ‘draggable’ component, such as the below code.

renderUsers = (item, index) => {
    return (
      <Draggable key={index} draggableId={index + " "} index={index}>
        {(provided) => (
          <div
            ref={provided.innerRef}
            {...provided.draggableProps}
            {...provided.dragHandleProps}
          >
            <div className="item">
              <div>{index + 1}</div>
              <div>
                <img src={item.avatar} alt="avatar" />
              </div>
              <div className="name">
                <div>{item.firstName}</div>
                <div>{item.lastName}</div>
              </div>
            </div>
          </div>
        )}
      </Draggable>
    );
  };

By the way! Don’t worry about the variables that pass through ‘ref’. It is the documentation, and we have to use them.

Good job! Drag an item and drop it to enjoy the result. Our app looks much interactive now, and if you have any problem with the codes, use this video and this Github link to address it.

How to build a drag and drop component in ReactJs using React Beautiful DND