Technology will become obsolete, design will remain

First, use scenarios

Drag and drop business usage scenarios have permeated all aspects of our business, especially on the mobile side. Side drag menu, drag card interaction, drag score and more.

This interaction allows us to provide users with more convenient interactive operations in limited event scenarios. Greatly improve user experience and product fluency.

React-DND

React-DnD is a set of React utilities that help you build complex drag-and-drop interfaces while maintaining coupling between components. It is ideal for applications like Trello and Storify, where dragging transfers data between different parts of the application, and components can change their appearance and application state in response to drag-and-drop events.

A team task collaboration platform like the one above is used by many companies. React-dnd is an excellent open source solution for this type of business scenario.

Next, let’s introduce how to use it.

Three, use method

3.1 installation

You need to install backend and React-DND at the same time.

Why with such a design, after the source code analysis will be detailed.

3.2 DndProvider injection

The DndProvider component provides the React-DND functionality for your application. It must be injected into the backend with the Backendc argument, but it can also be injected into a Window object.

Backend is a good design approach in React-DND. Can be understood as concrete drag and drop implementation.

DndProvider api

  • Backend: Mandatory. The DND backend can use two official HTML5Backend or TouchBackend, or write backend itself.
  • Context: Optional, the user configures the context of the backend, depending on the backend implementation.
  • Options: Configures backend objects that can be passed to backend for customization. There are examples.

3.3 useDrag declares the drag source

UserDrag is used to use the current component as a hook for the drag source.

Where the parameters returned by useDrag are

  • Arguments [0]: An object containing properties collected from the collect function. If Collect does not define a function, an empty object is returned.
  • Arguments [1]: Drag the connector function of the source. This must be attached to the draggable part of the DOM.
  • Arguments [2]: Connector functionality for dragging preview. This can be appended to the DOM preview section.

And then the arguments that useDrag passes in are

  • Item: required. A plain JavaScript object that describes the data to be dragged. This is the only information about the drag source that can be used to place the target
  • Item. type: Mandatory and must be a string, ES6 symbol. Only placed targets registered as the same type will respond to this item
  • PreviewOptions: optional. A plain JavaScript object that describes the drag preview option
  • Options: a normal object. If some of the component’s props are not scalar (that is, not raw values or functions), arePropsEqual(props, otherProps) specifies custom functions inside the Options object to improve performance. Unless you have a performance problem, don’t worry.
  • Begin (monitor) : This parameter is optional. The dragging operation starts. There is no need to return anything, but if an object is returned, it overrides the default properties of the item specification.
  • End (item, monitor) : Optional, end will be called when dragging stops.
  • CanDrag (monitor) : Optional. Use it to specify whether dragging is currently allowed. The default allows
  • IsDragging (Monitor) : Optional. By default, only the drag source that initiated the drag action is considered a drag
  • Collect: This function is optional.

3.4 useDrop claims to place sources

UseDrop is used to use the current component as the hook to place the target.

The parameters returned by useDrop are

  • Arguments [0]: An object containing properties collected from the collect function. If Collect does not define a function, an empty object is returned.
  • Arguments [1]: Drag the connector function of the source. This must be attached to the draggable part of the DOM.

And then the arguments that useDrag passes in are

  • Accept: required. String, ES6 symbol, an array of one of them, or functions that return one of the given components. This drop target will react only to items generated by a drag source of the specified type.
  • Options: optional. An ordinary object. If some of the component’s props are not scalar (that is, not raw values or functions), arePropsEqual(props, otherProps) specifies custom functions inside the Options object to improve performance. Unless you have a performance problem, don’t worry.
  • Drop (item, monitor): Optional. Called when a compatible item is placed on the target. You can return undefined or pure objects. If an object is returned, it becomes the drop result and can be used for the endDrag method monitor.getDropresult () in its drag source. This is useful if you want to perform different actions depending on which target is received. If you have nested drop targets, you can drop to test whether the nested targets have been processed by monitor.didDrop() and. Both this method and the source endDrag method are good places to trigger Flux actions. This method false is not called if canDrop() is defined and returns.
  • Hover (item, monitor): optional. Called when the project is hovered over a component. You can check monitor.isover ({shallow: true}) to test whether the hover has occurred only for the current target, or by nesting one. Unlike the drop() method, false will be called even if canDrop() is defined and returns this method. You can check if monitor.candrop () is the case.
  • CanDrop (item, monitor): Optional. Use it to specify whether the item is acceptable to the placing target. If you want to always allow it, simply ignore this method.
  • Collect: This function is optional.

3.5 Effect Display

As shown in the code above, the result can be seen in the GIF below.

Full Demo example: Portal

4. Source code analysis.

React-dnd: React-DND: React-DND: React-DND

4.1 Design Architecture

Let’s first parse from the source directory.

It’s divided into three parts

  • Backend Backend. (Scene specific DOM manipulation)
  • DND – the core of the core.
  • React – DND encapsulates the React plug-in.

So let’s take a look at how the source code is wrapped, starting with the API used in the above example, and then work our way down to the core.

4.2 DndProvider source

The entire code is written in typescript. Let’s look at it by module.

As you can see from the DndProvider component, the core returns the DndContext component. Like other container components, the React Context encapsulates a layer to pass shared values down. This reminds me of the same design pattern for Redux’s Provider.

(React. UseEffect) There is also an optimization logic here, if the global detection already has an instance, then clear this instance.

The Provider passes the value manager, which is obtained through the getDndContextValue method.

As shown in the code above, the getDndContextValue method creates a manager singleton with attributes like Backend context, Options, and debugMode.

Next, to verify our guess, take a look at the DndContext component code.

CreateContext with React. CreateContext.

And it creates a drag-and-drop instance, which you can think of as the total instance, which I’m going to use instead

So you can see the dnD-core core components from the DND-Core, except DragDropManager, BackendFactory, createDragDropManager.

DND -core source code will be covered later, we will first use the API slowly in-depth explanation.

4.3 useDrag

UseDrag drags the source, useDrag returns three parameters, let’s look at the function

The three parameters are result,connectDragSource(the connector that drags the source),connectDragPreview(the link preview function);

RagPreviewImage: ragPreviewImage: ragPreviewImage: ragPreviewImage: ragPreviewImage: ragPreviewImage

Renders an HTML Image element as a broken drag preview component.

Use Demo as:

The display effect is:

The horse head image shown above is what the Preview module provides.

Continuing with the useDrag section, we will touch on a module called the Connector. What is the connector? You can imagine it as a hook for a data bus. Obtained in the above code from the useDragSourceMonitor method.

The useDragSourceMonitor method returns two modules, monitor and Connector, for easy viewing. And the data is retrieved from the manager.getBackend.

The Manager instance is obtained via useContext and is the total instance injected by the Provider above.

The dragSource dragSource instance is retrieved from a hook in the Connector connector. The connector is retrieved from a Backend instance passed in by sourceConnector in useDragSourceMonitor.

The dragSourceRef, or DOM node, is retrieved from sourceConnector using the React.Ref parameter.

There are also many private boundary handling methods, such as:

See here some people may notice a usage, reconnect, this model is interesting, relink, update the data every time to re-establish link hooks, this piece can be said in the DND – the core module on, personal guess because DND – the core module USES the story.

This allows you to drag source – back – end – total instances.

4.4 useDrop

UseDrop places the source, again in terms of the API used, and the function returns two arguments, so let’s look at the method.

The source code returns result, connectDropTarget. The same as useDrag, but without the Preview instance, the placement source does not need this parameter.

ConnectDropTarget works the same way as connectDragSource.

Put source-back-total instances together.

Next, we continue to analyze the DND-Core source module in depth.

4.5 DragDropManager

React-dnd uses data rather than views as a source of facts, and when you drag something on the screen, you’re not dragging a component or DOM node. Instead, data preview lets the drag source “be dragged”. Dnd-core is officially centered around data, and Redux is used internally within React-DND. Let’s go ahead and analyze.

DND – Core core module is the most important is the total instance, look at the total instance builder function.

The total instance is inherited via DragDropManagerImpl(the implementation class of the total instance) and passed in the debugMode switch.

The back-end instance BackeDN is created through the back-end factory. Manager installs back-end instances.

Take a look at the DragDropManagerImpl source code, it’s a bit long, I’d like to delete a bit, but it’s all really good.

Let’s split it up from the top down.

MakeStoreInstance, creating an instance of Redux, you can see this but you know how Redux state management works. There is a debugMode parameter used to debug redux, which is passed in when the total instance is created. ReduxDevTools is a Google extension that needs to be installed yourself.

DragDropManagerImpl is strictly inherited from the DragDropManager interface.

Take a look at the constructor in the implementation class

First, an instance of Redux is created to fetch the store and bind it to the member property, inheriting DragDropMonitorImpl to listen to the implementation class, passing in the Store, passing in the registered implementation class. Get registration information and bind it to store. Subscribe to handleRefCountChange.

The subscribed handleRefCountChange function is as follows

Count is the total number of times the back-end dragged the source.

Next, process the actions logic and add DragDropActions.

Bind the Dispatch member function

The Three-piece Redux is now ready to go.

All other locations are bound member property functions.

So let’s continue with the logic of adding DragDropActions, what Actions are bound? Let’s see.

You can see that the bound Actions have

  • BeginDrag (start dragging)
  • PublishDragSource (publish the current drag source)
  • Hover (whether after)
  • Drop (drop)
  • EndDrag (drag ends)

Focus on the beginDrag module.

“BeginDrag” is an action.

Where we see the react-DND data driver core concept XYCoord coordinates, modify the coordinate method setClientOffset.

Look at the setClientOffset method, which is also an action.

Coordinate interface

To summarize the section we analyzed above, ReactDnD controls the preview position of the drag source through the interface in the form of coordinates, and moves the drag source to it if it can be determined to drop.

Combined with boundary function and most logic judgment, encapsulating DND-Core core logic (data-driven)

So where are the implementation drag-and-drop implementations and events handled?

4.6 backend

React DnD builds on the HTML5 drag-and-drop API. This is a reasonable default because it allows you to take a screenshot of a dragged DOM node and use it as a “drag preview” out of the box. Conveniently, you don’t have to do any drawing while the cursor is moving. The API is also the only way to handle file deletion events.

Unfortunately, the HTML5 drag-and-drop API also has some drawbacks. It doesn’t work on touch screens and offers fewer opportunities for customization on IE than other browsers.

That’s why HTML5 drag-and-drop support is pluggable in React DnD. You don’t have to use it. You can write other implementations based on touch events, mouse events, or other events entirely. This pluggable implementation is called the back end in React DnD. The library only ships with the HTML5 back end, but more may be added in the future.

The back ends act like the React integrated event system: they abstract browser differences and handle local DOM events. Despite the similarities, the React DnD back end does not rely on React or its synthetic event system. Behind the scenes, all the back ends convert DOM events to internal Redux actions that React DnD can handle.

The backend is designed to handle the scenarios described above, and React-Dnd supports custom backend. If your business scenario is special enough, you can write your own backend.

The back end is the implementation of events

Five, the END

Drag and drop comes in many forms and plugins. See the react-DND wheels, very good. If this article is of any help to you, please give me a thumbs up at 👍. Your thumbs up is my motivation to keep writing

Thanks to developers who contribute to open source projects.

  • The React – DnD: making;
  • React-DnD Docs: Docs
  • React-DnD Examples: Examples

Previous articles recommended:

  • How to improve team Productivity through UI Intelligent Code Generation
  • “The program design in the Drawing of Nine squares”
  • How to Build an Exception Capture Platform | Scene Reenactment
  • How to Build an Exception Capture Platform | Data Statistics