2

I'm trying to implement a simple drag preview that overrides the default browser behavior, but I can't seem to find the right pattern, and the documentation refers to a simple set of examples without explaining the larger context of how layers work.

Here's some code: doesn't work currently -- not sure how to link it so that the preview for the dragged item shows [Item] and not for other items. How do I make this link? What am I missing here?

import React, { Component } from 'react';
import { DragDropContext, DragSource, DropTarget, DragLayer } from 'react-dnd';
import HTML5Backend, { getEmptyImage } from 'react-dnd-html5-backend';

const types = {
  Item: 'ITEM'
};

class Item extends Component {
  componentDidMount() {
   this.props.connectDragPreview(getEmptyImage());
  }

  render() {
    const { name, connectDragSource, isDragging } = this.props;
    return connectDragSource(
        <div>
          <div>
            {name}
          </div>
        </div>
      )
    );
  }
};

const DraggableItem = DragSource(types.Item,
  {
    beginDrag(props) {
      const { name } = props;
      return {
        name
      };
    }
  },
  (connect, monitor) => {
    return {
      connectDragSource: connect.dragSource(),
      connectDragPreview: connect.dragPreview(),
      isDragging: monitor.isDragging()
    };
  }
)(Item);

const ItemPreview = ({ item, isDragging }) => {
  if (!isDragging)
    return null;
  return (
    <div>[{item ? item.name : null}]</div>
  )
};

const ItemLayer = DragLayer(
  monitor => {
    return {
      isDragging: monitor.isDragging(),
      item: monitor.getItem()
    };
  }
)(ItemPreview);

const Dnd = () => {
  return (
    <div>
      <DraggableItem name="Item A" />
      <DraggableItem name="Item B" />
      <DraggableItem name="Item C" />
      <ItemLayer />  {/* Clearly wrong. */}
    </div>
  );
};

export default DragDropContext(HTML5Backend)(Dnd);

For what it's worth, I've found ReactDnd up to this point extremely easy to use and leverage. It's the previewing piece that I think could benefit from further documentation, and I'm happy to add it once I have a more thorough understanding of how this all works.

Adam Donahue
  • 1,618
  • 15
  • 18

1 Answers1

1

The answer here is, as I expected, obvious in hindsight, but not particularly clear from the documentation: one must set the (x, y) position of the preview component itself, via, typically, an inline style that uses props from the DragLayer container's monitor to compute its correct position.

Once that's in place, everything works.

Adam Donahue
  • 1,618
  • 15
  • 18