packages/docsite/markdown/docs/00 Quick Start/Overview.md
React DnD is unlike most of the drag and drop libraries out there, and it can be intimidating if you've never used it before. However, once you get a taste of a few concepts at the heart of its design, it starts to make sense. I suggest you read about these concepts before the rest of the docs.
Some of these concepts resemble the Flux and Redux architectures.
This is not a coincidence, as React DnD uses Redux internally.
Like Flux (or Redux), React DnD uses data, and not the views, as the source of truth. When you drag something across the screen, we don't say that a component, or a DOM node is being dragged. Instead, we say that an item of a certain type is being dragged.
What is an item? An item is a plain JavaScript object describing what's being dragged. For example, in a Kanban board application, when you drag a card, an item might look like { cardId: 42 }. In a Chess game, when you pick up a piece, the item might look like { fromCell: 'C5', piece: 'queen' }. Describing the dragged data as a plain object helps you keep the components decoupled and unaware of each other.
What is a type, then? A type is a string (or a symbol) uniquely identifying a whole class of items in your application. In a Kanban board app, you might have a 'card' type representing the draggable cards and a 'list' type for the draggable lists of those cards. In Chess, you might only have a single 'piece' type.
Types are useful because, as your app grows, you might want to make more things draggable, but you don't necessarily want all the existing drop targets to suddenly start reacting to the new items. The types let you specify which drag sources and drop targets are compatible. You're probably going to have an enumeration of the type constants in your application, similar to how you may have an enumeration of the Redux action types.
Drag and drop is inherently stateful. Either a drag operation is in progress, or it isn't. Either there is a current type and a current item, or there isn't. This state has to live somewhere.
React DnD exposes this state to your components via a few tiny wrappers over the internal state storage called the monitors. The monitors let you update the props of your components in response to the drag and drop state changes.
For each component that needs to track the drag and drop state, you can define a collecting function that retrieves the relevant bits of it from the monitors. React DnD then takes care of timely calling your collecting function and merging its return value into your components' props.
Let's say you want to highlight the Chess cells when a piece is being dragged. A collecting function for the Cell component might look like this:
function collect(monitor) {
return {
highlighted: monitor.canDrop(),
hovered: monitor.isOver()
}
}
It instructs React DnD to pass the up-to-date values of highlighted and hovered to all the Cell instances as props.
If the backend handles the DOM events, but the components use React to describe the DOM, how does the backend know which DOM nodes to listen to? Enter the connectors. The connectors let you assign one of the predefined roles (a drag source, a drag preview, or a drop target) to the DOM nodes in your render function.
In fact, a connector is passed as the first argument to the collecting function we described above. Let's see how we can use it to specify the drop target:
function collect(connect, monitor) {
return {
highlighted: monitor.canDrop(),
hovered: monitor.isOver(),
connectDropTarget: connect.dropTarget()
}
}
In the component's render method, we are then able to access both the data obtained from the monitor, and the function obtained from the connector:
render() {
const { highlighted, hovered, connectDropTarget } = this.props;
return connectDropTarget(
<div className={classSet({
'Cell': true,
'Cell--highlighted': highlighted,
'Cell--hovered': hovered
})}>
{this.props.children}
</div>
);
}
The connectDropTarget call tells React DnD that the root DOM node of our component is a valid drop target, and that its hover and drop events should be handled by the backend. Internally it works by attaching a callback ref to the React element you gave it. The function returned by the connector is memoized, so it doesn't break the shouldComponentUpdate optimizations.
So far we have covered the backends which work with the DOM, the data, as represented by the items and types, and the collecting functions that, thanks to the monitors and the connectors, let you describe what props React DnD should inject into your components.
But how do we configure our components to actually have those props injected? How do we perform the side effects in response to the drag and drop events? Meet the drag sources and the drop targets, the primary abstraction units of React DnD. They really tie the types, the items, the side effects, and the collecting functions together with your components.
Whenever you want to make a component or some part of it draggable, you need to wrap that component into a drag source declaration. Every drag source is registered for a certain type, and has to implement a method producing an item from the component's props. It can also optionally specify a few other methods for handling the drag and drop events. The drag source declaration also lets you specify the collecting function for the given component.
The drop targets are very similar to the drag sources. The only difference is that a single drop target may register for several item types at once, and instead of producing an item, it may handle its hover or drop.
React DnD uses the HTML5 drag and drop API. It is a reasonable default because it screenshots the dragged DOM node and uses it as a “drag preview” out of the box. It's handy that you don't have to do any drawing as the cursor moves. This API is also the only way to handle the file drop events.
Unfortunately, the HTML5 drag and drop API also has some downsides. It does not work on touch screens, and it provides less customization opportunities on IE than in other browsers.
This is why the HTML5 drag and drop support is implemented in a pluggable way in React DnD. You don't have to use it. You can write a different implementation, based on touch events, mouse events, or something else entirely. Such pluggable implementations are called the backends in React DnD.
The library currently ships with the HTML backend, which should be sufficient for most web applications. There is also a Touch backend that can be used for mobile web applications.
The backends perform a similar role to that of React's synthetic event system: they abstract away the browser differences and process the native DOM events. Despite the similarities, React DnD backends do not have a dependency on React or its synthetic event system. Under the hood, all the backends do is translate the DOM events into the internal Redux actions that React DnD can process.
Now you should have an understanding of the various moving pieces of React DnD:
Modern React applications have replaced the Higher-Order-Component pattern with hooks. Hooks are a feature of React, introduced in 16.8, that allow for developers to write stateful function components. They are also fantastic for managing stateful components, and also for interacting with external stateful systems (*cough* like a Drag-and-Drop engine *cough*).
If you are unfamiliar with React hooks, refer to the React blog post, Introducing Hooks.
React-DnD provides hooks that connect your components to the DnD engine, and allow you to collect monitor state for rendering.
For an overview of the hooks-based API, refer to the Hooks Overview page.
Now you know enough about React DnD to explore the rest of the documentation!
The hooks overview documentation page is great places to start. Or jump straight into the tutorial app and build a chess game!