Using react-beautiful-dnd to implement drag and drop between lists

Using react-beautiful-dnd to implement drag and drop between lists

Why choose react-beautiful-dnd

Compared with react-dnd, react-beautiful-dnd is more suitable for dragging between lists, supports mobile terminals, and is easier to use.

Basic usage

Basic Concepts

  • DragDropContext: Construct a draggable range
  • onDragStart: Drag start callback
  • onDragUpdate: callback during dragging
  • onDragEnd: callback when dragging ends
  • Droppable - the area where the draggable block can be placed
  • Draggalbe - The element that can be dragged

How to use

Put the code you want to be able to drag and drop in DragDropContext

import { DragDropContext } from 'react-beautiful-dnd';

class App extends React.Component {
  onDragStart = () => {
    /*...*/
  };
  onDragUpdate = () => {
    /*...*/
  }
  onDragEnd = () => {
    // the only one that is required
  };

  render() {
    return (
      <DragDropContext
        onDragStart={this.onDragStart}
        onDragUpdate={this.onDragUpdate}
        onDragEnd={this.onDragEnd}
      >
        <div>Hello world</div>
      </DragDropContext>
    );
  }
}

Determine the droppable area

import { DragDropContext, Droppable } from 'react-beautiful-dnd';

class App extends React.Component {
  // ...
  render() {
    return (
      <DragDropContext
        onDragStart={this.onDragStart}
        onDragUpdate={this.onDragUpdate}
        onDragEnd={this.onDragEnd}
      >
        <Droppable droppableId="droppable-1">
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              style={{ backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey' }}
              {...provided.droppableProps}
            >
              <h2>I am a droppable!</h2>
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    );
  }
}
  • Required DroppableId (string) that uniquely identifies the application's droppable. Do not change this ID, especially while dragging
  • provided.placeholder: placeholder (this placeholder is the default and generally does not meet the requirements)
  • snapshot: The current drag state, which can be used to change the appearance of the Droppable while being dragged

Use Draggable to wrap the drag element in the Droppable area

import { DragDropContext, Droppable, Draggable } from 'react-beautiful-dnd';

class App extends React.Component {
  // ...

  render() {
    return (
      <DragDropContext
        onDragStart={this.onDragStart}
        onDragUpdate={this.onDragUpdate}
        onDragEnd={this.onDragEnd}
      >
        <Droppable droppableId="droppable-1">
          {(provided, snapshot) => (
            <div
              ref={provided.innerRef}
              style={{ backgroundColor: snapshot.isDraggingOver ? 'blue' : 'grey' }}
              {...provided.droppableProps}
            >
              <Draggable draggableId="draggable-1" index={0}>
                {(provided, snapshot) => (
                    <div
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                    >
                      <h4>My draggable</h4>
                    </div>
                )}
              </Draggable>
              {provided.placeholder}
            </div>
          )}
        </Droppable>
      </DragDropContext>
    );
  }
}
  • A Draggable must always be contained within a Droppable
  • DraggablebId (string): A unique ID must exist, and index (also required if it is a traversal key). Do not change this ID, especially while dragging.

When dragging ends, change the source data

onDragEnd = result => {
  const { source, destination, draggableId } = result;
  if (!destination) {
    return;
  }

  // Modify the source and target arrays, delete the dragged element from the source array, and insert it into the target array this.setState({
    xxx: xxx,
  });
}

Problems encountered during use

Add a custom placeholder to the drag target area

When react-beautiful-dnd is dragged to the target area, a space will be automatically left between the elements in the target area for the current drag element. The distance of this space is the size of the Draggable element in the target area (but does not include the margin of the element, which is also a pitfall. The solution will be discussed below).

Therefore, you can use absolute positioning within this distance and add a custom placeholder. Specific approach: calculate the left & top distance of the current custom placeholder element, and update these two distances in the dragUpdate event. Please refer to beatiful-dnd-custom-placeholder-demo

When dragging, modifying the transform property of the dragged element causes the drag to get stuck somewhere and the dragged element is placed in the wrong position

In the official documentation, there is a description that roughly says that the draggable element uses position: fixed positioning, but will be affected by transform.

#### Warning: `position: fixed`

`react-beautiful-dnd` uses `position: fixed` to position the dragging element. This is quite robust and allows for you to have `position: relative | absolute | fixed` parents. However, unfortunately `position:fixed` is [impacted by `transform`](http://meyerweb.com/eric/thoughts/2011/09/12/un-fixing-fixed-elements-with-css-transforms/) (such as `transform: rotate(10deg);`). This means that if you have a `transform: *` on one of the parents of a `<Draggable />` then the positioning logic will be incorrect while dragging. Lame! For most consumers this will not be an issue.

To get around this you can [reparent your <Draggable />](/docs/guides/reparenting.md). We do not enable this functionality by default as it has performance problems.

The following solution is provided: Use createPortal to hang the drag element on an empty parent element. Please refer to issue: transform on parent messes up dragging positioning

But this method does not solve my problem, because there is still a need for custom placeholder. When dragging, it is also necessary to calculate the left distance of the placeholder, which means that it is necessary to obtain the child elements under the parentNode of the current dragged element. If createPortal is used, the original parentNode of the dragged element cannot be obtained, so the createPortal solution is abandoned. The effect of transform: scale is achieved by changing width and height.

To drag an element on mobile, you need to long-press it.

The official documentation states that in mobile scenarios, finger operations on draggable elements cannot be determined to be tap, force press, or scroll, so you need to long press the element to determine whether it is a drag.

Starting a drag: long press
A user can start a drag by holding their finger πŸ‘‡ on an element for a small period of time πŸ•‘ (long press)

When dragging an element and hovering it at the target position, the distance of the vacated insertion space is inaccurate. This is the problem mentioned above. The free distance of the placeholder left between Draggables is the distance of a Draggable, but does not include the margin of the Dragglable. Please refer to this issue.

Finally, padding is used to control the distance between Draggables, so that the space vacated during dragging includes the padding.

Summarize

react-beautiful-dnd is relatively easy to use. As of March 2021, v13.1.0 was released and it is relatively active. I hope the above pitfalls will be helpful to everyone.

References

Official website beautiful-dnd
react-beautiful-dnd Getting Started Tutorial

This is the end of this article about using react-beautiful-dnd to implement drag and drop between lists. For more relevant react list drag and drop content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of gantt chart draggable and editable (highcharts can be used for vue and react)
  • Typescript+react to achieve simple drag and drop effects on mobile and PC
  • react-beautiful-dnd implements component drag and drop function
  • More than 100 lines of code to implement react drag hooks
  • React.js component implements drag and drop sorting component function process analysis
  • React sample code to implement drag and drop function
  • React.js component implements drag-and-drop copy and sortable sample code
  • Let's talk again about a series of problems caused by React.js implementing native js drag effects
  • Thoughts on implementing native js drag effects based on React.js
  • React implements simple drag and drop function

<<:  Oracle deployment tutorial in Linux environment

>>:  Programs to query port usage and clear port usage in Windows operating system

Recommend

MySQL 8.0.17 installation and simple configuration tutorial under macOS

If you don’t understand what I wrote, there may b...

MySQL full backup and quick recovery methods

A simple MySQL full backup script that backs up t...

MySQL master-slave configuration study notes

● I was planning to buy some cloud data to provid...

Vue encapsulates the public function method of exporting Excel data

vue+element UI encapsulates a public function to ...

An article to help you learn CSS3 picture borders

Using the CSS3 border-image property, you can set...

Basic installation process of mysql5.7.19 under winx64 (details)

1. Download https://dev.mysql.com/downloads/mysql...

Implementation of Docker deployment of Nuxt.js project

Docker official documentation: https://docs.docke...

Mobile front-end adaptation solution (summary)

I searched online and found that many interviews ...

Detailed explanation of JS homology strategy and CSRF

Table of contents Overview Same Origin Policy (SO...

JS implements the sample code of decimal conversion to hexadecimal

Preface When we write code, we occasionally encou...

Detailed explanation of mkdir command in Linux learning

Table of contents Preface 1. Basic knowledge of f...

Detailed explanation of using Vue.prototype in Vue

Table of contents 1. Basic Example 2. Set the sco...

Summary of MySQL log related knowledge

Table of contents SQL execution order bin log Wha...

Detailed tutorial on installing nacos in docker and configuring the database

Environment Preparation Docker environment MySQL ...

SMS verification code login function based on antd pro (process analysis)

Table of contents summary Overall process front e...