Why react-beautiful-DND

Compared with react-DND, react-beautiful-DND is more suitable for dragging and dropping between lists. It supports mobile devices and is easier to use.

Basic usage

The basic concept

  • DragDropContext: Builds a range that can be dragged
  • OnDragStart: Drag to start the callback
  • OnDragUpdate: Callback in drag
  • OnDragEnd: Callback at the end of drag
  • Droppable – Area where drag blocks can be placed
  • Draggalbe – Element that can be dragged

Method of use

  1. Put whatever code you want to be able to drag and drop into the 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> ); }}Copy the code
  1. Determine the placable area Dropppable
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> ); }}Copy the code
  • The required DroppableId (string) that uniquely identifies the droppable of the application. Do not change this ID especially when dragging
  • Provided. Placeholder: placeholder (this placeholder is the default, and generally does not fit the requirements well)
  • Snapshot: The current drag state, which can be used to change the appearance of the Droppable while being dragged
  1. Use Draggable to wrap drag elements in the Dropppable 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> ); }}Copy the code
  • Draggable must always be included in Droppable
  • DraggablebId (string) : There must be a unique ID, and index (also needed for traversal keys) do not change this ID, especially when dragging
  1. When the drag is complete, change the source data
onDragEnd = result => { const { source, destination, draggableId } = result; if (! destination) { return; } this.setState({XXX: XXX,}); }Copy the code

Problems encountered during use

Add custom placeholders to the drop target area

This space is the size of the Draggable element in the target area (but not the element’s margin, which is also a pit). The solution is described below.

Therefore, absolute positioning can be used in this distance, adding custom placeholders. Calculate the left & Top distance of the current custom placeholder element and update the two distances in the dragUpdate event (see Beatiful-dnd -custom-placeholder-demo)

While dragging, modify the transform property of the drag element, causing the drag element to get stuck somewhere and put the drag element in the wrong place

The draggable element takes position: Fixed, but is affected by the 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.Copy the code

The solution is as follows: Use createPortal to hang drag elements on empty parent elements (see issue: Transform on Parent Messes Up Positioning)

However, this approach doesn’t solve my problem because there are still custom placeholder requirements. In addition, you need to calculate the distance between the placeholder left and the placeholder left, so you need to obtain the children of the parent parentNode of the placeholder element. If you use createPortal, you cannot obtain the parent parentNode of the placeholder element. Transform: Scale by changing width and height.

Dragging elements on the mobile side requires long pressing on the element (long-press)

According to the official documentation, in mobile scenarios, a finger operation on the draggable element cannot be identified as tap, force press, or scroll, so long pressing on the element can be identified as 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)
Copy the code

Incorrect insertion distance created when dragging an element hovering over the target location

This is what has been mentioned above. The vacant distance left between the Draggable placeholder is a Draggable distance, but does not include the margin of the Dragglable. Please refer to this issue.

Finally, the padding is used to control the distance between the Draggable, so that the space generated in the drag space includes the padding.

conclusion

React-beautiful-dnd is easy to learn, and v13.1.0 was released in March 2021.

The resources

  • Website beautiful – DND
  • React-beautiful-dnd Tutorial