react-dropzone: prevent inner element from showing file picker

3.6k views Asked by At

I'm currently using the react-dropzone plugin and encountered a use case that's not exactly described in the documentations.

Basically, I have the following elements:

  • An outer dropzone that should allow both
    • Drag-and-drop, and
    • Native file picker on click
  • An inner button that does not show the native file picker on click

The problem I'm having right now is to stop the native file picker from showing up when the inner button is clicked.

To illustrate my example, you can paste this code into the View Code section.

import React from 'react';
import {useDropzone} from 'react-dropzone';

function Dropzone(props) {
  const {getRootProps, getInputProps, open, acceptedFiles} = useDropzone({
    // Disable click and keydown behavior
    noKeyboard: true
  });

  const files = acceptedFiles.map(file => (
    <li key={file.path}>
      {file.path} - {file.size} bytes
    </li>
  ));

  return (
    <div className="container">
      <div {...getRootProps({className: 'dropzone'})}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here</p>
        <InnerButton />
      </div>
      <aside>
        <h4>Files</h4>
        <ul>{files}</ul>
      </aside>
    </div>
  );
}

function InnerButton(props) {
  const { getRootProps } = useDropzone({ noClick: true }); // doesn't stop the parent's input file picker

  return (
    <button
      {...getRootProps({
        onClick: (event) => event.stopPropagation(), // this is bad for many reasons
      })}
      type="button">
      This button should not open the file picker
    </button>
  );
}

<Dropzone />

I figured that using event.stopPropagation() is one way but I've read that it should be avoided for many reasons (source 1, source 2). I tried using noClick: true in the inner button but it doesn't work - most likely because it can't stop the parent's <input> tag.

Is there another approach that I should try, other than using stopPropagation?

1

There are 1 answers

0
Jia Jian Goi On BEST ANSWER

I got an answer on GitHub, posting it here in case anyone else encounters the same question.

There's no way around it. You have to use stopPropagation() to stop the event from bubbling up the DOM. Your other option is to use noClick on the parent as well.

noClick only disables opening the file selector when clicking on the dropzone node. It does not prevent the event from bubbling.

The only thing we can do is to provide a noClickBubbling option that calls stopPropagation(), but the user can already do that.