Building a Simple Drag-and-Drop UI with React Hooks


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. The onDragEnd 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 a Draggable 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.

  1. Check if the item was dropped outside: If the destination is null, we do nothing.
  2. 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.
  3. 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 using setItems.

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!


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *