Comparative Study on the Most Complete React Drag-and-Drop Sorting Component Library

Click on the front-end Q above to follow the official account

Reply to join the group, join the front-end Q technology exchange group

1. Introduction to usage

Based on the drag and drop function of react, there are several popular libraries:

  1. react-dnd

  2. react-beautiful-dnd

  3. dnd-kit

  4. react-sortable-hoc

React-dnd

(1) Basic concepts

  • Backend: The backend is mainly used to smooth out browser differences, handle DOM events, and convert DOM events into redux actions inside React DnD. You can use HTML5 to drag and drop the backend, or you can customize it Backend implementation of touch and mouse event simulation

  • Item: Use a data object to describe the currently dragged element, for example { cardId: 42 }

  • Type: Similar to the actions types enumeration constant in redux, it defines the drag and drop types supported in the application

  • Monitor: Drag and drop is inherently stateful. Either a drag operation is in progress, or it isn’t. Either there is the current type and the current item, or not, React DnD uses Monitor to store these states and provide queries

  • Connector: Connect components and Backend, allowing Backend to get DOM

  • DragSource: This is a high-level component, use it to wrap your component to make it a drag source

  • DropTarget: This is a high-level component, use it to wrap your component to make it a drop source

  • DragDropContext: Wraps the root component and provides a drag-and-drop context

(2) Simple demo

91f5441e8cd5a791ddcd8d937d012338.jpeg

codesandbox.io/s/github/re…[1]

react-beautiful-dnd

(1) Basic concepts

ae7ea7004ffc06780e818b65029231d1.gif
11dd3d37d871fab3b9bd5671627f34cc.jpeg

It mainly contains three components.

  1. DragDropContext : Used to wrap the dragging root component, both Draggable and Droppable need to be wrapped in DragDropContext

  2. Draggable is used to wrap the components you need to drag, so that the components can be dragged (make it draggable)

  3. Droppable is used to wrap components that receive dragged elements, so that components can be placed (dropped on it)

(2) Simple demo

e80ee9edf2f83834f0ac72d3613c81ef.jpeg
a1340949213b7d5220908abcf20d0568.jpeg

https://juejin.cn/post/codesandbox.io/s/k260nyxq9v

dnd-kit

(1), basic concepts

f69ae12c58a7f5fe15f1ec5fa0910067.jpeg
3616e35e90249fa4e892dbe31fbadfd7.jpeg

1. DndContext is used to wrap the drag root component, both Draggable and Droppable need to be wrapped in DndContext
2. Droppable is used to package components that receive dragged elements, so that components can be placed
3. Draggable is used to wrap the components you need to drag, so that the components can be dragged
4. Sensors are used to detect different input methods to initiate drag operations, respond to movement, and end or cancel operations. The built-in sensors are:

  • pointer

  • mouse

  • touch

  • keyboard

5. Modifiers allow you to dynamically modify the motion coordinates detected by the sensor. They can be used for a wide range of use cases such as:

  • Limit motion to a single axis

  • Constrains the movement of the draggable node container’s bounding rectangle

  • Constrains the movement of the draggable node’s scroll container’s bounding rectangle

  • Apply resistance or clamping motion

(2), simple demo

a4b1101e6e713ba3ddddb6d88190c227.jpeg

5fc05e08a4a65d0021ae0bf2-ffprtowwny.chromatic.com/iframe.html…[2]

react-sortable-hoc

(1), basic concepts
1. SortableContainer Drag and drop the sorted container
2. SortableElement drag and drop sorted elements

(2), simple demo

ba0b2831cc0b958be5dda667db569455.jpeg

https://juejin.cn/post/codesandbox.io/s/react-sortable-hoc-starter-o104x95y86

3. Antd compatible table

How to use it with the table component of antd?

7f2d7e6cbd575f8e8ccc5daff40c06f9.jpeg

react-dnd uses antd-table :codesandbox.io/s/tuo-zhuai…[3]

2657d50d2fea137c190ce396445cc045.jpeg

react-sortable-hoc uses antd-table:codesandbox.io/s/tuo-zhuai…[4]

e15e5b242a930ccf3dced22ebf98b274.jpeg

react-beautiful-dnd-antd-table: codesandbox.io/s/react-bea…[5]

dnd-kit: stackblitz.com/edit/react-…[6] (the demo does not work, github.com/clauderic/d…[7] According to this issue, it is the reason of antd-design itself,

758fb3c665594972a9eae5db22ec3c50.png

Enhanced table component under the hood)

4. Tree compatible

Antd’s own tree drag and drop sorting:
codepen.io/huxinmin/em…[8]

The disadvantage of the built-in tree drag is

  1. The effect of dynamic real-time dragging and changing positions cannot be realized, and the position change must occur after the dragging is completed

  2. Need to modify a lot of built-in styles

Trees can simply be thought of as lists nested within each other.

efcf9cafd8c72d28971f4e2691bc1f1d.jpeg

react-dnd: codesandbox.io/s/crazy-hoo…[9]

1f4b184727230e6127cac84220a55c95.jpeg

react-sortable-hoc:codesandbox.io/embed/react…[10]

0064a47354a98a24b18ab5d9408a92be.jpeg

react-beautiful-dnd-antd-table:codesandbox.io/embed/react…[11]

22bcecb498e10ee8d279fb204097dd26.jpeg

dnd-kit:codesandbox.io/embed/react…[12]

5. Mobile compatibility

f063b009f0640360a9c2c472be4bbddd.jpeg

react-dnd: codesandbox.io/embed/react…[13]

55d1fa0a7e325ebc148207804b20c20e.jpeg

react-beautiful-dnd-antd-table: codesandbox.io/s/react-bea…[14]

0e06f54fa4d5cf090ad0bb8a25b8113f.jpeg

react-sortable-hoc uses antd-table:codesandbox.io/s/tuo-zhuai…[15]

f7cd45b2f495212bb327467942accc27.jpeg

dnd-kit:5fc05e08a4a65d0021ae0bf2-hbqxtqukzi.chromatic.com/iframe.html…[16]

6. Infinite scroll

The best way is to use virtual-list, but the support of these libraries is also different.

5f511290e58c8da81638a8b428b73235.jpeg

react-dnd:codesandbox.io/embed/react…[17]

Use requestAnimationFrame for performance optimization, and can also be used with other virtual list libraries.

7383dbed560f2706137a45d938f842aa.jpeg

dnd-kit:5fc05e08a4a65d0021ae0bf2-hbqxtqukzi.chromatic.com/iframe.html…[18]

This demo uses the react-tiny-virtual-list [19] library.

aa61e0a5ab2c97ed08f91694f681db5c.jpeg

react-sortable-hoc:clauderic.github.io/react-sorta…[20]

Using react-virtualized

f4d05ce1a75431d746fc95158c89ca51.jpeg

react-beautifule-dnd:react-beautiful-dnd.netlify.app/iframe.html…[21]

React-virtualized is used.

7. Summary comparison

  • react-dnd[22]

  • complete documentation

  • github star number 16.4k

  • The maintenance and update are good, and there has been an update and maintenance in the last month

  • higher learning costs

  • Moderate function

  • Mobile compatibility, good

  • Moderate number of examples

  • Many concepts, complicated to use

  • Components can be decoupled

  • react-beautiful-dnd[23]

  • complete documentation

  • github star number 24.8k

  • The maintenance and update are good, and there have been updates and maintenance in the last three months

  • higher learning costs

  • Moderate ease of use

  • feature rich

  • Excellent mobile compatibility

  • Lots of examples

  • is a higher-level abstraction built specifically for vertical and horizontal lists, without the extensive functionality that react-dnd provides

  • Beautiful appearance, good accessibility, physical perception makes people feel more realistic when moving objects

  • The development concept is drag and drop, does not support copy/clone

  • dnd-kit[24]

  • complete documentation

  • github star number 2.8k

  • The maintenance and update are good, and there has been an update and maintenance in the last month

  • Moderate cost of study

  • Moderate ease of use

  • Moderate function

  • Mobile Compatibility, Moderate

  • Lots of examples

  • copy/clone not seen

  • react-sortable-hoc[25]

  • less documentation

  • github star number 9.5k

  • The maintenance and update are good, and there have been updates and maintenance in the last three months

  • lower learning costs

  • Ease of use

  • simple function

  • Mobile Compatibility, Moderate

  • Moderate number of examples

  • Drag and drop to another container is not supported

  • copy/clone not seen

  • Mainly focus on the sorting function, and the rest of the drag and drop functions are not rich

If it is to be used in combination with antd’s table, the simplest component is react-sortable-hoc. For infinite scrolling, although there are many examples of react-sortable-hoc, but few source codes, you can consider using react-beautiful-dnd. If it is a tree-like drag and drop, you can use the tree that comes with antd if the requirements are not high, and react-beautiful-dnd if you require high points. Compatible with mobile terminals, you can consider using react-sortable-hoc or react-beautiful-dnd.

8. How to encapsulate a simple drag and drop component by yourself

1. HTML5 drag and drop API

First, to make the element draggable, the draggable property needs to be set:

<img draggable="true">

Then there are several drag and drop processing functions:

  1. ondrag drag and drop in progress

  2. ondragend/ondragstart start drag and drop and end drag and drop

  3. ondragover When the element or selected text is dragged over a target target (fires every 100 ms).

  4. ondraenter/ondragleave the source object starts entering/leaving the range of the target object

  5. ondrop The source object is dragged and dropped on the target object

For data transfer, use event.dataTransfer, which has the following APIs:

  • setData: Add drag data, this method receives two parameters, the first parameter is the data type (customizable), the second parameter is the corresponding data

  • getData: Reverse operation, get data, only receive one parameter, namely the data type

  • clearData: clear data

  • setDragImage: You can customize the image next to the mouse during drag and drop

  • The effectAllowed: attribute specifies an effect that is allowed for drag and drop operations. The copy operation is used to indicate that the data being dragged will be copied from the current location to the dropped location. The _move operation is used to specify that the data being dragged will be moved. The link_action is used to indicate that some form of relationship or connection will be created between the source and the drop location.

2. Function and architecture design

  1. Use react-hooks

  2. Drag and drop object drag component, drag and drop object drop component, drag and drop context dndContext

  3. Support mobile terminal

  4. Support sorting

3. Code

The Drag component uses:

<Drag index={1} id='1'>
  <div>Wrapped draggable components</div>
</Drag>

Drag component implementation:

import { FC } from "react";

interface DragProps {
  index: number;
  id: string | number;
}

const Drag: FC<DragProps> = (props) => {
  const startDrag = (ev) => {
    // transfer data
    ev.dataTransfer.setData("index", props.index);
    ev.dataTransfer.setData("id", props.id);
  };

  return (
    <div draggable onDragStart={startDrag}>
      {props. children}
    </div>
  );
};

export default Drag;

The Drop component uses:

<Drop>
 <Drag index={1} id='1'>
   <div>Wrapped draggable components</div>
 </Drag>
</Drop>

Drop component implementation:

import { FC, useContext } from "react";
import { Context } from "./DndContext";

const Drop: FC = (props) => {
  const { onDragOver, onDragEnd } = useContext(Context);
  const dragOver = (ev) => {
    ev.preventDefault();
    if (onDragOver) onDragOver();
  };

  const drop = (ev) => {
    // retrieve data
    const oldIndex = ev.dataTransfer.getData("index");
    // Get the Y-axis coordinate at the end of the drag
    const Y = ev.clientY;
    // Simple calculation, set the height to 20
    // I'm lazy here, the actual calculation is very complicated
//Generally, there are two implementation ideas, one is to calculate based on the position, and the other is to set the drag source to be placed, and then get
    const height = 20;
    const newIndex = Math. floor(Y / height);

    if (oldIndex) {
      if (onDragEnd) onDragEnd(Number(oldIndex), newIndex);
    }
  };

  return (
    <div onDragOver={dragOver} onDrop={drop}>
      {props. children}
    </div>
  );
};

export default Drop;

The DndContext component uses:

<DndContext
        onDragEnd={(oldIndex, newIndex) => {
          setData(arrayMove(data, oldIndex, newIndex));
        }}
        onDragOver={() => {}}
      >
        <Drop>
          {data. map((i, index) => (
            <Drag key={i.id} id={i.id} index={index}>
              <div className="item">{i.text}</div>
            </Drag>
          ))}
        </Drop>
      </DndContext>

DndContext component implementation:

import { createContext, FC } from "react";

export interface TContext {
  onDragOver: () => void;
  onDragEnd: (oldIndex: number, newIndex: number) => void;
}

const Context = createContext<TContext>({} as TContext);

const DndContext: FC<TContext> = (props) => {
  return (
    <Context.Provider
      value={<!-- -->{
        onDragEnd: (oldIndex, newIndex) => {
          props.onDragEnd(oldIndex, newIndex);
        },
        onDragOver: () => {
          props.onDragOver();
        }
      }}
    >
      {props. children}
    </Context.Provider>
  );
};

export { Context };
export default DndContext;

If you need to deal with mobile compatibility, you can use the following libraries:
github.com/timruffles/…[26]

Fourth, optimize space

  1. After dragging and dropping, the position is calculated

  2. Real-time exchange position during dragging

  3. performance optimization

  4. exception handling etc.

  5. drag process style

  6. Drag direction, x-axis and y-axis

  7. etc.

5. Online code

Specific online code example: codesandbox.io/embed/react…[27]

3f518f39667dbc585b9d35af876e0882.jpeg

Author: green fire

Article address: https://juejin.cn/post/7062625911312646175

Previous recommendations
The details of async and await devils that you don't know
Hurry up! The Tencent WeChat team is recruiting, and the resume will be sent directly to the interviewer!
collect! The most comprehensive Vue front-end code style guide in history

at last

Welcome to add me on WeChat, pull you into the technology group, long-term exchange and learning...

Welcome to pay attention to "Front-end Q", study the front-end seriously, and be a professional technical person...

Click to watch and support me