How to Attach Drag & Drop Event Listeners to a React component How to Attach Drag & Drop Event Listeners to a React component reactjs reactjs

How to Attach Drag & Drop Event Listeners to a React component


You don't need to use props. You can just add all the events inside your DropZone component.

http://codepen.io/jzmmm/pen/bZjzxN?editors=0011

This is where i add the events:

  componentDidMount() {    window.addEventListener('mouseup', this._onDragLeave);    window.addEventListener('dragenter', this._onDragEnter);    window.addEventListener('dragover', this._onDragOver);    window.addEventListener('drop', this._onDrop);    document.getElementById('dragbox').addEventListener('dragleave', this._onDragLeave);  }

Your render method:

  render() {    return (      <div>        {this.props.children}        <div id="dragbox" className={this.state.className}>          Drop a file to Upload        </div>      </div>    );  }

As you can see in componentDidMount, i added an eventlistener to #dragbox as well. Because once you drag a file over the page, #dragbox is under the mouse cursor, so it needs a dragleave in case you decide you don't want to drop the file there.

Also, dragover is needed to capture the drop

Then in my App component, i can use it like this:

class App extends React.Component {  render() {    return (      <DropZone>        <div>          <h1>Drag A File Here...</h1>        </div>      </DropZone>    );  }}


Version of @mnsr's answer using styled-components library and React Hooks

const DragBox = styled.div(({ isVisible }: { isVisible }) =>    isVisible        ? `        position: fixed;        display: flex;        border: 15px dashed white;        width: 100%;        height: 100%;        z-index: 2000;        top: 0;        left: 0;        right: 0;        bottom: 0;        flex: 1;        justify-content: center;        align-items: center;        text-align: center;        font-size: 30px;        font-weight: 600;        color: white;        letter-spacing: 1px;        margin: auto;`        : 'display: none;');const DropZone = ({ children }) => {    const [isVisible, setIsVisible] = useState(false);    const onDragEnter = useCallback((e) => {        setIsVisible(true);        e.stopPropagation();        e.preventDefault();        return false;    }, []);    const onDragOver = useCallback((e) => {        e.preventDefault();        e.stopPropagation();        return false;    }, []);    const onDragLeave = useCallback((e) => {        setIsVisible(false);        e.stopPropagation();        e.preventDefault();        return false;    }, []);    const onDrop = useCallback((e) => {        e.preventDefault();        const files = e.dataTransfer.files;        console.log('Files dropped: ', files);        // Upload files        setIsVisible(false);        return false;    }, []);    useEffect(() => {        window.addEventListener('mouseup', onDragLeave);        window.addEventListener('dragenter', onDragEnter);        window.addEventListener('dragover', onDragOver);        window.addEventListener('drop', onDrop);        return () => {            window.removeEventListener('mouseup', onDragLeave);            window.removeEventListener('dragenter', onDragEnter);            window.removeEventListener('dragover', onDragOver);            window.removeEventListener('drop', onDrop);        };    }, [onDragEnter, onDragLeave, onDragOver, onDrop]);    return (        <div>            {children}            <DragBox                className="bg-secondary"                isVisible={isVisible}                onDragLeave={onDragLeave}            >                Drop files to Upload            </DragBox>        </div>    );};