Reputation: 7199
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
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
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
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