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

Detailed explanation of the method of comparing dates in MySQL

If there is a table product with a field add_time...

Detailed explanation of Cgroup, the core principle of Docker

The powerful tool cgroup in the kernel can not on...

Docker installation of Nginx problems and error analysis

question: The following error occurred when insta...

How to change the dot in the WeChat applet swiper-dot into a slider

Table of contents background Target Effect Ideas ...

Detailed explanation of mysql deadlock checking and deadlock removal examples

1. Query process show processlist 2. Query the co...

Parsing the commonly used v-instructions in vue.js

Table of contents Explanation of v-text on if for...

Troubleshooting ideas and solutions for high CPU usage in Linux systems

Preface As Linux operation and maintenance engine...

Google Translate Tool: Quickly implement multilingual websites

Google China has released a translation tool that ...

Vue routing returns the operation method of restoring page status

Route parameters, route navigation guards: retain...

Summary of MySQL database like statement wildcard fuzzy query

MySQL error: Parameter index out of range (1 >...

Mobile Internet Era: Responsive Web Design Has Become a General Trend

We are in an era of rapid development of mobile In...

Vue song progress bar sample code

Note that this is not a project created by vue-cl...

Implementation of Nginx forwarding matching rules

1. Regular expression matching ~ for case-sensiti...

A Preliminary Study on Vue Unit Testing

Table of contents Preface Why introduce unit test...