DEV Community 👩‍💻👨‍💻

Cover image for Drag n Drop with React-Beautiful-DND
Asad Ur Rehman
Asad Ur Rehman

Posted on

Drag n Drop with React-Beautiful-DND

REACT DRAG AND DROP

There are many React libraries that helps in making Drag and Drop react components.

In this blog, We will be using react library called react-beautiful-dnd for creating DND components. React-Beautiful-DND is one of the most user friendly and easy to use Drag and Drop (DND) react library, developed by the creators of JIRA, Alex Reardon.

React-Beautiful-DND

Brief Introduction

In React-Beautiful-DND library the DND components are created using 3 main components

  • <DragDropContext/> => defines the area for entire drag n drop operation

  • <Droppable/> => defines the area where Draggable items can be dropped

  • <Draggable/>=> defines the actual item that can be dragged around and dropped in Droppable area

"Each DragDropContext can have multiple Droppables and each Droppables can have multiple Draggables defined inside them."

BRD Library Installation

npm i react-beautiful-dnd

Create DragDropContext

We will import DragDropContext from library react-beautiful-dnd and wrap the whole App inside this context. This will wrap other two components, Droppable and Draggable BRD components. There are props such as onDragStart, onDragUpdate and onDragEnd defined but onDragEnd is more than enough to perform reordering, adding and removing items.

import "./styles.css";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import { useState } from "react";
Enter fullscreen mode Exit fullscreen mode
 <div className="App">
      <DragDropContext onDragEnd={onDragEnd}>
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              style={getListStyle(snapshot.isDraggingOver)}
            >
              {fruitItems.map((item, index) => (
                    <div key={item.id} >
                      {item.Title}
                    </div>
              ))}
              {provided.placeholder}
            </div>
          )}
      </DragDropContext>
    </div>
Enter fullscreen mode Exit fullscreen mode

Create Droppable and Draggable

we will import Droppable and Draggable from library react-beautiful-dnd. Draggagle must be nested inside Droppable and Droppable should be nested inside DragDropContext.

Droppable defines the droppable area where items can be dragged and dropped. Each droppable component will have a unique droppableId prop. Droppable component provides variables such as :

  • provided.innerRef: a react reference variable to manipulate the DOM elements

  • provided.droppableProps: provides the default CSS styling for drag and drop functionality

  • provided.placeholder: provides an extra space in Droppable area for the item that is currently being dragged.

  • snapshot: snapshot.isDraggingOver can be used to get the drag&drop state to apply conditional CSS styling.

**Draggable **defines the actual item that needs to be dragged. It must be nested inside Droppable component. We must provide values for

  • draggableIdfor uniquely identifying the dragged items.

  • index: for identifying the data in the list that is currently being dragged in source and in destination identifying the data in the list below which the dragged item must be placed.

Modified App.js after adding Droppable and Draggable

import "./styles.css";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
import { useState } from "react";

export default function App() {
  const [fruitItems, setFruitItems] = useState([
    { id: "1", Title: "Apple" },
    { id: "2", Title: "Mango" },
    { id: "3", Title: "Peach" },
    { id: "4", Title: "Grapes" },
    { id: "5", Title: "BlueBerry" },
    { id: "6", Title: "StrawBerry" }
  ]);

  const onDragEnd = (result) => {
    const newItems = Array.from(fruitItems);
    const [removed] = newItems.splice(result.source.index, 1);
    newItems.splice(result.destination.index, 0, removed);
    setFruitItems(newItems);
  };

  const grid = 8;

  const getItemStyle = (isDragging, draggableStyle) => ({
    // some basic styles to make the items look a bit nicer
    userSelect: "none",
    padding: grid * 2,
    margin: `0 0 ${grid}px 0`,

    // change background colour if dragging
    background: isDragging ? "lightgreen" : "lightblue",

    // styles we need to apply on draggables
    ...draggableStyle
  });

  const getListStyle = (isDraggingOver) => ({
    background: isDraggingOver ? "lightblue" : "grey",
    padding: grid,
    width: 250
  });
  return (
    <div className="App">
      <DragDropContext onDragEnd={onDragEnd}>
        <Droppable droppableId="droppable">
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              style={getListStyle(snapshot.isDraggingOver)}
            >
              {fruitItems.map((item, index) => (
                <Draggable key={item.id} draggableId={item.id} index={index}>
                  {(provided, snapshot) => (
                    <div
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                      style={getItemStyle(
                        snapshot.isDragging,
                        provided.draggableProps.style
                      )}
                    >
                      {item.Title}
                    </div>
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Testing

Here is the code in CodeSandbox
React-Beautiful-dnd

Top comments (1)

Collapse
ivanjeremic profile image
Ivan Jeremic

A dnd library for react which in my opinion is even better is dnd-kit

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.