The background,

Recently, I met a new requirement in my work, which required the implementation of drag and drop of a certain component. The first project to meet this requirement was definitely to ask Baidu and search on the largest gay dating website. Finally, god helped me find the 17K STAR React drag and drop library — React DnD.

Two, simple use

2.1 installation

npm install react-dnd -S // react-dnd package, its core package
npm install react-dnd-html5-backend -S // The libraries required by the underlying implementation of drag
Copy the code

2.2 Three core points

Using the React DnD library, I found that the most useful part of the library contains a component and two Hook apis:

  1. DndProvider components
  2. UseDrag function
  3. UseDrop function

2.2.1 DndProvider components

If you want some content to use the React DnD capability, you need to wrap this part with DndProvider, and its receiving parameters are as follows:

  • Backend: Mandatory. A React DnD back end. React-dnd-html5-backend, react-dnd-touch-backend, and react-dnd-test-backend are three official documents. React-dnd-html5-backend is commonly used.
  • Context: Optional. Used to configure the back-end context. It depends on the back-end implementation.
  • Options: Optional. The option object used to configure the backend. It depends on the back-end implementation.

Let’s look at a simple use of this component:

import {DndProvider} from 'react-dnd';
import {HTML5Backend} from 'react-dnd-html5-backend';

function App() {
  return (
    <div className="App">
      <DndProvider backend={HTML5Backend}>Drag and drop the content here</DndProvider>
    </div>
  );
}

export default App;
Copy the code

2.2.2 useDrag function

Now that you know the entire manipulation space, the next thing you need to know is where to drag from. The library provides the useDrag Hook API, which allows a DOM element to drag.

  1. parameter

(1) spec: a specification object or function that creates a specification object, as shown below:

1) type

The value must be a string or Symbol, and can be placed only if the value drop is the same as this value.

2) item

Must describe the data being dragged

3) previewOptions

Optional, a simple object that describes the drag preview option;

4) options

Optional, a simple object

(5) end item, the monitor)

Optionally, this function is called when the drag stops;

6) canDrag (monitor)

Optionally, use it to specify whether dragging is currently allowed;

7) isDragging (monitor)

Optionally, by default, only the drag source that initiates the drag action is considered a drag;

8) collect

Optional, listening function

  1. The return value

The return value is an array containing the following contents:

Collected: an object that contains attributes collected from collect and returns an empty object if Collect does not define a function; Drag: The connector function of the dragger, which must be attached to the dragable part of the DOM; DragPreview: a connector feature for dragPreview that can be attached to the preview section of the DOM;

  1. Establish a connection with the drag section

Bind drag or dragPreview to the drag source using the ref attribute.

Here’s a look at the use of the useDrag part

import {useDrag} from 'react-dnd';

const SourceBox = props= > {
    const {children} = props;

    /* collected: an object that contains attributes collected from collect and returns an empty object if collect does not define a function * drag: DragPreview: the connector function for dragPreview can be attached to the preview section of the DOM
    const [collected, drag, dragPreview] = useDrag({
        // Only if drop is the same as this value can be dropped
        type: 'box'.// Describe the data to drag
        item: {
            detail: 'I can drag data!! '
        },
        // Drag to stop the hand end will be called
        end: (item, monitor) = > {
            // getDropResult() gets the result of the release
            console.log('monitor.getDropResult():', monitor.getDropResult());
            // Whether the source has been dropped at target
            console.log('monitor.didDrop()', monitor.didDrop());
        },
        // Specifies whether dragging is currently allowed
        canDrag: monitor= > {
            return true;
        },
        // The listener function
        collect: (monitor, props) = > {
            return {
                isDragging: monitor.isDragging() }; }});return (
        <div ref={drag}>
            {children}
        </div>
    );
};

export default SourceBox;

Copy the code

2.2.3 useDrop function

To place the content in the target location, the useDrop function is provided, as follows:

  1. parameter

(1) spec: a specification object or function that creates a specification object, as shown below:

1) accept

Must, a string, this place target will react only to items generated by the specified type of drag source;

2) options

Optional, a normal object;

3) Drop (item, monitor)

Optional, called when compatible items are placed on the target;

4) hover (item, monitor)

Optional, called when the project is hovering over the component;

5) canDrop (item, monitor)

Optionally, use it to specify whether the drop target accepts the drag;

6) collect

Optional, listening function

  1. The return value

The return value is an array containing the following contents:

Collected: an object that contains attributes collected from collect and returns an empty object if Collect does not define a function; Drop: a connector function for placing the target, which must be attached to the placing part of the DOM;

  1. Establish a connection with the placement section

The DROP is joined to the drop part through the ref attribute.

Let’s look at the use of the useDrop section

import {useDrop} from "react-dnd";

const TargetBox = () = > {
    const [collected, drop] = useDrop({
        // This place target will react only to items generated by the drag source of the specified type
        accept: 'box'.// called when compatible items are placed at the target
        drop: (item, monitor) = > {
            console.log('I've been put in the target!! ')},// The listener function
        collect: monitor= > {
            return {
                // Whether to overlap
                isOver: monitor.isOver(),
                // Can be placed
                canDrop: monitor.canDrop(),
                item: monitor.getItem(),
                didDrop: monitor.didDrop() }; }});return (
        <div ref={drop}>
            <div className="targetBox">This is the block that was placed</div>
        </div>
    );
};

export default TargetBox;
Copy the code

2.3 Monitor Details

There are many options mounted on useDrag and useDrop, many of which have monitor objects mounted on which many methods are mounted. Here is a brief overview of the main methods, as follows:

  1. Method on monitor on drag

2. Drop method on monitor

Three, effect drawing

  1. Drag and drop before

  1. Drag and drop the

Drag-and-drop content moves with the mouse

  1. Drag and drop after

When we drag and release the mouse, we print out the contents of the drop and then the contents of the end, so we want to do some processing in the SourceBox. If we change the React data in the drop, we will get an error.

4. Learning and feeling

The data of this library are all the same. In the process of using it, I met some pits. Next, I will share these pits with you, so as to prevent the follow-up from falling into them.

  1. The call time of end is later than the call time of DROP. Therefore, only the data processing after release in END can ensure the correctness of the system. If the data in STATE or React redux is updated in DROP, an error will occur.
  2. Item data is a bridge between Drag and Drop. The item data defined in Drag can be retrieved from monitor.getitem ();
  3. The return value of the drop callback is the bridge between drop and Drag, which can be returned by monitor.getDropresult () in end;
  4. Some of the location functions mounted on Monitor are not necessarily suitable for all scenarios, and dom-related location operations need to be introduced.