Stevan Tosic
Stevan Tosic

Reputation: 7199

React dropzone - dragLeave event fired when dragging file over dropzone

I am using React dropzone for file upload

<DropZone
            accept='.pdf,.pptx,.ppt,.docx,.doc,.xls,.xlsx,.xslx,.png,.xsl,.jpg,.jpeg,.gif,.zip'
            onDrop={ files => {
              this.handleFileDrop(files);
              this.dragLeaveHandler();
            } }
            onDragEnter={ this.dragOverHandler }
            onDragLeave={ this.dragLeaveHandler }
            multiple={ false }
            style={ { height: '100%' } }
          >

  dragOverHandler = () => {
    console.log('enter');
    this.setState({
      isDragOver: true,
    });
  };

  dragLeaveHandler = () => {
    console.log('exit');
    this.setState({
      isDragOver: false,
    });
  };

When a file is moving above the drop zone onDragLeave event fires simultaneously.

Should I use some other events? How can I fix this issue?

Upvotes: 3

Views: 2969

Answers (3)

Iskren Ivov Chernev
Iskren Ivov Chernev

Reputation: 311

One way I managed to solve this, is by counting the number of enter/leave events. When you enter the outermost element you receive the first dragEnter. Then if you move further in, you get a dragEnter for an inner element and a dragLeave for the outer one. So far you got 2 enters and one leave, so you're still in. Make sure to reset in the drop handler.

const DropZone = () => {
  const [hang, setHang] = useState(false);
  const hangCount = useRef(0);
  const updateHang = (amt) => {
    if (amt) { hangCount.current += amt; }
    else { hangCount.current = 0; }
    setHang(hangCount.current > 0);
  }
  const drop = (ev) => {
    ev.preventDefault();
    updateHang(0); // reset
    /* rest of drop logic */
  }
  return <div
    onDrop={drop}
    onDragEnter={() => updateHang(1)}
    onDragLeave={() => updateHang(-1)}
    className={hang ? 'hang' : ''}
  ></div>;
}

Upvotes: 0

Shay
Shay

Reputation: 2100

You could use pointer-events: none; on the element(s) that are firing the drag leave. That should still allow the dropped event and getting the accepted file though would stop overriding the dropzone events.

Upvotes: 4

Jemi Salo
Jemi Salo

Reputation: 3751

The problem you're facing is most likely caused by the DOM events dragEnter and dragLeave getting messed up instead of any flaw in the react-dropzone package. Some elements may cause hovering over them in certain positions not to register as hovering over their parent element. For example, there is a thin sliver at the top edge of any plain string rendered inside a block displayed element. Most commonly this happens inside a <p> tag.

Without seeing the children rendered inside your dropzone, it is impossible to give a specific fix. Generally, you will have to mess with the styling of the children, though. <p> tags for example will not be a problem if their size is set to 0 pixels or if they're replaced with <span> tags. Both options will disrupt the displaying of the children, which is unfortunatley unavoidable.

As for using other events, you're out of luck. The DropZone component relies on the onDragEnter and onDragLeave HTML DOM events. Therefore any fix you might come up with won't fix the component itself.

All in all, it's an unfortunate issue that just has to be dealt with. The simplest way to deal with it is to just have at most one piece of text inside the dropzone and to set its size to 0 pixels with css: height: 0px;. Regular <div> elements won't cause issues, so you can craft an intricate dropzone using them.

Upvotes: 2

Related Questions