React Beautiful DnD (Drag and Drop) is a powerful and flexible library that allows developers to add draggable and droppable elements to their React applications. It is built on top of the popular react-dnd
library and provides a set of higher-order components that can be used to create draggable and droppable lists, boards, and other interactive elements.
Our example app is using the React Beautiful DnD library, which allows for drag-and-drop functionality. The code creates three lists of items – fruits, vegetables, and vehicles – and renders them in the UI. Users can drag and drop items between the lists and the status will update to indicate the item’s current location.
Here is an example of how to use React Beautiful DnD to create a simple draggable list:
Install React Beautiful DnD Library
Start by installing the React Beautiful DnD library in your react application by executing the below npm command:
npm install react-beautiful-dnd
Next update the App component with below code:
import React, { useState } from "react";
import { DragDropContext, Droppable, Draggable } from "react-beautiful-dnd";
const fruits = [
{ id: 1, name: "Apple", color: "lightgreen" },
{ id: 2, name: "Banana", color: "lightgreen" },
{ id: 3, name: "Mango", color: "lightgreen" },
{ id: 4, name: "Orange", color: "lightgreen" },
{ id: 5, name: "Grapes", color: "lightgreen" },
];
const vegetables = [
{ id: 6, name: "Carrot", color: "lightblue" },
{ id: 7, name: "Potato", color: "lightblue" },
{ id: 8, name: "Tomato", color: "lightblue" },
{ id: 9, name: "Cucumber", color: "lightblue" },
{ id: 10, name: "Onion", color: "lightblue" },
];
const vehicles = [
{ id: 11, name: "Car", color: "pink" },
{ id: 12, name: "Bike", color: "pink" },
{ id: 13, name: "Bus", color: "pink" },
{ id: 14, name: "Truck", color: "pink" },
{ id: 15, name: "Train", color: "pink" },
];
const App = () => {
const [fruitsList, setFruitsList] = useState(fruits);
const [vegetablesList, setVegetablesList] = useState(vegetables);
const [vehiclesList, setVehiclesList] = useState(vehicles);
const [status, setStatus] = useState("");
const onDragEnd = (result) => {
const { destination, source, draggableId } = result;
if (!destination) {
return;
}
if (
destination.droppableId === source.droppableId &&
destination.index === source.index
) {
return;
}
const sourceList =
source.droppableId === "fruits"
? fruitsList
: source.droppableId === "vegetables"
? vegetablesList
: vehiclesList;
const destinationList =
destination.droppableId === "fruits"
? fruitsList
: destination.droppableId === "vegetables"
? vegetablesList
: vehiclesList;
const item = sourceList.find((i) => i.id.toString() === draggableId);
sourceList.splice(source.index, 1);
destinationList.splice(destination.index, 0, item);
if (destination.droppableId === "fruits") {
setFruitsList([...destinationList]);
} else if (destination.droppableId === "vegetables") {
setVegetablesList([...destinationList]);
} else {
setVehiclesList([...destinationList]);
}
setStatus(
`Item: ${item.name} moved from ${source.droppableId} to ${destination.droppableId}`
);
};
return (
<>
<div>
<pre>{status}</pre>
</div>
<div
style={{
display: "flex",
justifyContent: "center",
alignItems: "center",
height: "100vh",
}}
>
<DragDropContext onDragEnd={onDragEnd}>
<div
style={{
display: "flex",
justifyContent: "space-between",
width: "80%",
}}
>
<Droppable droppableId="fruits">
{(provided, snapshot) => (
<div
ref={provided.innerRef}
style={{
background: snapshot.isDraggingOver
? "lightgreen"
: "green",
padding: 8,
width: "30%",
minHeight: "100px",
}}
{...provided.droppableProps}
>
<h2>Fruits</h2>
{fruitsList.map((item, index) => (
<Draggable
key={item.id}
draggableId={item.id.toString()}
index={index}
>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
userSelect: "none",
padding: 16,
margin: "0 0 8px 0",
minHeight: "50px",
backgroundColor: snapshot.isDragging
? "lightgreen"
: item.color,
...provided.draggableProps.style,
}}
>
{item.name}
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
<Droppable droppableId="vegetables">
{(provided, snapshot) => (
<div
ref={provided.innerRef}
style={{
background: snapshot.isDraggingOver ? "lightblue" : "blue",
padding: 8,
width: "30%",
minHeight: "100px",
}}
{...provided.droppableProps}
>
<h2>Vegetables</h2>
{vegetablesList.map((item, index) => (
<Draggable
key={item.id}
draggableId={item.id.toString()}
index={index}
>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
userSelect: "none",
padding: 16,
margin: "0 0 8px 0",
minHeight: "50px",
backgroundColor: snapshot.isDragging
? "lightblue"
: item.color,
...provided.draggableProps.style,
}}
>
{item.name}
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
<Droppable droppableId="vehicles">
{(provided, snapshot) => (
<div
ref={provided.innerRef}
style={{
background: snapshot.isDraggingOver ? "pink" : "red",
padding: 8,
width: "30%",
minHeight: "100px",
}}
{...provided.droppableProps}
>
<h2>Vehicles</h2>
{vehiclesList.map((item, index) => (
<Draggable
key={item.id}
draggableId={item.id.toString()}
index={index}
>
{(provided, snapshot) => (
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
userSelect: "none",
padding: 16,
margin: "0 0 8px 0",
minHeight: "50px",
backgroundColor: snapshot.isDragging
? "pink"
: item.color,
...provided.draggableProps.style,
}}
>
{item.name}
</div>
)}
</Draggable>
))}
{provided.placeholder}
</div>
)}
</Droppable>
</div>
</DragDropContext>
</div>
</>
);
};
export default App;
The code starts by importing the necessary libraries and dependencies for the project, including React, the useState hook, and the DragDropContext
, Droppable
, and Draggable
components from the react-beautiful-dnd library.
Next, three arrays are defined that contain data for different types of items (fruits, vegetables, and vehicles). Each item in the arrays has an id, name, and color property.
The App component is defined as a functional component that uses React’s useState hook to manage the state of the fruitsList
, vegetablesList
, and vehiclesList
arrays, as well as a status string.
The onDragEnd
function is defined as a callback for the DragDropContext
component’s onDragEnd
prop. This function is called whenever a draggable item is dropped in a droppable area. It takes a single argument, the result of the drag and drop action, which contains information about the source and destination of the item, as well as the id of the draggable item.
Within the onDragEnd
function, a series of conditional statements are used to check if the draggable item was dropped in a valid destination. If not, the function exits. If the destination is valid, the item is removed from the source array and added to the destination array.
Depending on the destination droppableId
, the relevant state is updated to reflect the change in the arrays. The status string is also updated to show the movement of item.
The App component’s return statement renders the components that make up the UI of the application. It starts by rendering a <div> that displays the current status of the drag and drop action.
The next <div> is used to center the drag and drop area on the screen and has some styling applied to it. Inside this div, the DragDropContext component is rendered.
Within the DragDropContext component, a <div> is rendered with some styling applied to it. This div contains three Droppable components, one for each of the fruitsList
, vegetablesList
, and vehiclesList
arrays.
Each Droppable component is passed a droppableId
prop that corresponds to the array it represents. Inside each Droppable component, a map function is used to render a Draggable component for each item in the corresponding array.
The Draggable component is passed a key, draggableId
, and index prop that correspond to the item’s id, id as a string and index in the array. Inside each Draggable component, the item’s name and color are rendered, and some styling is applied to it.
The Draggable component also receives the provided object, which contains props that need to be spread on the DOM element. The innerRef
prop is used to pass a ref to the top-level DOM node, and the draggableProps
and dragHandleProps
props are used to make the element draggable.
Finally, run your app to show the dynamically created lists so that you can drag items inter between the lists.
Conclusion
In conclusion, this code uses the React library and the react-beautiful-dnd library to create a drag and drop functionality for different lists of items. The items are grouped into three different lists: fruits, vegetables, and vehicles. Each list is represented by a Droppable component, which allows for items to be dragged and dropped within the same list or between different lists.
The onDragEnd function is used to handle the logic of moving items between lists and updating the state of each list. Additionally, the status of the last item moved is displayed for the user. Overall, this code demonstrates the use of the react-beautiful-dnd library to implement a functional and user-friendly drag and drop feature in a React application.
Leave a Reply