Drag n Drop with React-Beautiful-DND
Tags: beginners, react, dnd, tutorial
Published: 2022-07-26 05:48:09

## 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


![] (https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g8b8s8b8rztbj9zjaopt.gif)

-  `<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.


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

```js
 <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>
```

## 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

- `draggableId `for 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
```js
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>
  );
}

```

## Testing
Here is the code in CodeSandbox
[React-Beautiful-dnd](https://codesandbox.io/s/react-beautiful-dnd-test-8twpd6?file=/src/App.js)