New to React DnD? Read the overview before jumping into the docs.

DragLayer 

This is an advanced feature.

For the most use cases, the default rendering of the HTML5 backend should suffice. However, its drag preview has certain limitations. For example, it has to be an existing node screenshot or an image, and it cannot change midflight.

Sometimes you might want to perform the custom rendering. This also becomes necessary if you're using a custom backend. DragLayer lets you perform the rendering of the drag preview yourself using just the React components. It is a higher-order component accepting one required parameter that is described below.

To use DragLayer, don't forget to wrap the top-level component of your app in a DragDropContext.

Signature 

DragLayer uses partial application. After specifying its only parameter with the first call, you need to pass your React component class as the only parameter in the second call. This signature makes DragLayer usable as an ES7 decorator. Read the overview for a more detailed explanation of the decorators and the higher-order components.

import { DragLayer } from 'react-dnd'; @DragLayer(collect) export default class CustomDragLayer { /* ... */ }

Parameters 

  • collect: Required. The collecting function. It should return a plain object of the props to inject into your component. It receives a single monitor parameter. Read the overview for an introduction to the monitors and the collecting function. See the collecting function described in detail in the next section.

  • options: Optional. A plain object. If some of the props to your component are not scalar (that is, are not primitive values or functions), specifying a custom arePropsEqual(props, otherProps) function inside the options object can improve the performance. Unless you have performance problems, don't worry about it.

The Collecting Function 

The collecting function signature is similar to the collecting functions of DragSource and DropTarget, except that it doesn't have a connect parameter because the drag layer is not interactive and only reflects the drag state. The collecting function is called any time the global drag state changes, including the coordinate changes, so that your component can provide a timely updated custom drag preview. You can ask the monitor for the client coordinates of the dragged item.

Parameters 

  • monitor: An instance of DragLayerMonitor. You can use it to query the information about the current drag state, including the coordinates. Read the DragLayerMonitor documentation for a complete list of monitor methods, or read the overview for an introduction to the monitors.

Return Value 

DragLayer wraps your component and returns another React component.
For easier testing, it provides an API to reach into the internals:

Static Properties 

  • DecoratedComponent: Returns the wrapped component type.

Instance Methods 

  • getDecoratedComponentInstance(): Returns the wrapped component instance.

Example 

import React, { PropTypes } from 'react'; import ItemTypes from './ItemTypes'; import BoxDragPreview from './BoxDragPreview'; import { DragLayer } from 'react-dnd'; const layerStyles = { position: 'fixed', pointerEvents: 'none', zIndex: 100, left: 0, top: 0, width: '100%', height: '100%' }; function getItemStyles(props) { const { currentOffset } = props; if (!currentOffset) { return { display: 'none' }; } const { x, y } = currentOffset; const transform = `translate(${x}px, ${y}px)`; return { transform: transform, WebkitTransform: transform }; } @DragLayer(monitor => ({ item: monitor.getItem(), itemType: monitor.getItemType(), currentOffset: monitor.getSourceClientOffset(), isDragging: monitor.isDragging() })) export default class CustomDragLayer { static propTypes = { item: PropTypes.object, itemType: PropTypes.string, currentOffset: PropTypes.shape({ x: PropTypes.number.isRequired, y: PropTypes.number.isRequired }), isDragging: PropTypes.bool.isRequired }; renderItem(type, item) { switch (type) { case ItemTypes.BOX: return ( <BoxDragPreview title={item.title} /> ); } } render() { const { item, itemType, isDragging } = this.props; if (!isDragging) { return null; } return ( <div style={layerStyles}> <div style={getItemStyles(this.props)}> {this.renderItem(itemType, item)} </div> </div> ); } }