Published on 1.11.2019
Drag-and-drop interfaces are essential for creating interactive, user-friendly UIs. They’re great for managing lists, organizing items, and providing a more engaging user experience. In this tutorial, we’ll walk through how to implement a drag-and-drop UI in a React app using React Hooks and the popular react-beautiful-dnd library.
Why Use React Beautiful DnD?
The react-beautiful-dnd library is a powerful and flexible solution for drag-and-drop interactions. It provides an intuitive API and ensures smooth user interactions with built-in support for accessibility and responsiveness.
In this tutorial, we’ll be creating a sortable list where users can reorder list items by dragging them around.
Step 1: Setting Up the Project
To begin, let’s set up a new React project and install the necessary dependencies.
If you don’t have a React app set up already, create one by running the following commands:
npx create-react-app drag-and-drop-ui
cd drag-and-drop-ui
npm install react-beautiful-dnd
npm start
This will create a new React app and install react-beautiful-dnd
for handling drag-and-drop interactions.
Step 2: Create the List Component
Now that we have our environment set up, we can start building the drag-and-drop interface. Create a new component called DragAndDropList.js
inside the src
directory.
Here’s the initial code for a simple draggable list:
// src/DragAndDropList.js
import React, { useState } from 'react';
import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';
const DragAndDropList = () => {
const initialItems = [
{ id: '1', content: 'Item 1' },
{ id: '2', content: 'Item 2' },
{ id: '3', content: 'Item 3' },
{ id: '4', content: 'Item 4' },
];
const [items, setItems] = useState(initialItems);
// Function to handle the drag-and-drop reorder
const onDragEnd = (result) => {
const { destination, source } = result;
// If no destination (i.e., item dropped outside valid area)
if (!destination) return;
// If the item was dropped in the same place, do nothing
if (destination.index === source.index) return;
// Reordering the items
const reorderedItems = Array.from(items);
const [removed] = reorderedItems.splice(source.index, 1); // Remove the item from the source position
reorderedItems.splice(destination.index, 0, removed); // Insert the item at the destination position
// Updating the state with the reordered items
setItems(reorderedItems);
};
return (
<DragDropContext onDragEnd={onDragEnd}>
<Droppable droppableId="droppable">
{(provided) => (
<ul
{...provided.droppableProps}
ref={provided.innerRef}
style={{ listStyleType: 'none', padding: 0 }}
>
{items.map((item, index) => (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided) => (
<li
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
...provided.draggableProps.style,
padding: '10px',
margin: '5px 0',
backgroundColor: '#f4f4f4',
border: '1px solid #ccc',
borderRadius: '4px',
}}
>
{item.content}
</li>
)}
</Draggable>
))}
{provided.placeholder}
</ul>
)}
</Droppable>
</DragDropContext>
);
};
export default DragAndDropList;
Step 3: Explanation of Key Components
In the code above, we are using three key components from react-beautiful-dnd
:
DragDropContext
: This component provides the drag-and-drop context for our app. TheonDragEnd
function is passed as a prop to handle when a drag operation ends.Droppable
: This defines the area where items can be dropped. In our case, it wraps the entire list of items.Draggable
: Each individual list item is wrapped in aDraggable
component, which allows each item to be dragged.
onDragEnd
Function
The onDragEnd
function is responsible for handling the drag-and-drop logic. It receives the result
object, which contains information about the source and destination of the dragged item.
- Check if the item was dropped outside: If the
destination
isnull
, we do nothing. - Check if the item was dropped in the same place: If the destination index is the same as the source index, we return early to avoid unnecessary state updates.
- Reorder the list: We make a copy of the current list using
Array.from(items)
and reorder the items based on the source and destination indices. Then, we update the state with the reordered items usingsetItems
.
Styling the List
In this example, the list is styled with basic CSS properties such as padding, margin, background color, and borders. The draggable items are given a light gray background color and rounded corners for a clean look.
Step 4: Using the Drag-and-Drop Component in Your App
Now that we’ve created our drag-and-drop list, let’s use it in the main App.js
file.
// src/App.js
import React from 'react';
import DragAndDropList from './DragAndDropList';
function App() {
return (
<div className="App">
<h1>Drag-and-Drop List</h1>
<DragAndDropList />
</div>
);
}
export default App;
Step 5: Running the App
Now that everything is set up, you can start the app and test the drag-and-drop functionality. When you drag and drop an item in the list, the order of the items will update accordingly.
npm start
Your drag-and-drop list should now be working!
Conclusion
In this post, we’ve built a simple drag-and-drop UI using React Hooks and the react-beautiful-dnd library. We implemented a sortable list, where users can reorder items by dragging and dropping them. This functionality can be easily extended to other use cases, such as drag-and-drop file uploads or task management boards.
With react-beautiful-dnd
, we’re able to create smooth, user-friendly drag-and-drop interactions without having to build the complex logic ourselves.
Happy coding, and enjoy building your interactive UIs!