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";
<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 elementsprovided.droppableProps
: provides the default CSS styling for drag and drop functionalityprovided.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
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 </span><span class="p">${</span><span class="nx">grid</span><span class="p">}</span><span class="s2">px 0
,
<span class="c1">// change background colour if dragging</span>
<span class="na">background</span><span class="p">:</span> <span class="nx">isDragging</span> <span class="p">?</span> <span class="dl">"</span><span class="s2">lightgreen</span><span class="dl">"</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">lightblue</span><span class="dl">"</span><span class="p">,</span>
<span class="c1">// styles we need to apply on draggables</span>
<span class="p">...</span><span class="nx">draggableStyle</span>
});
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
Top comments (1)
A dnd library for react which in my opinion is even better is dnd-kit