react-dropzone: запретить внутреннему элементу показывать средство выбора файлов

#reactjs #react-dropzone

#reactjs #реагировать-dropzone

Вопрос:

В настоящее время я использую плагин react-dropzone и столкнулся с вариантом использования, который точно не описан в документации.

В принципе, у меня есть следующие элементы:

  • Внешняя dropzone, которая должна разрешать оба
    • Перетаскивание и
    • Собственное средство выбора файлов on click
  • Внутренняя кнопка, которая не отображает собственное средство выбора файлов on click

Проблема, с которой я сейчас сталкиваюсь, заключается в том, чтобы остановить отображение собственного средства выбора файлов при нажатии внутренней кнопки.

Чтобы проиллюстрировать мой пример, вы можете вставить этот код в раздел просмотра кода.

 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 />
  

Я полагал, что использование event.stopPropagation() — это один из способов, но я читал, что его следует избегать по многим причинам (источник 1, источник 2). Я пытался использовать noClick: true in the inner button, но это не работает — скорее всего, потому, что он не может остановить родительский <input> тег.

Есть ли другой подход, который я должен попробовать, кроме использования stopPropagation ?

Ответ №1:

Я получил ответ на GitHub, разместив его здесь на случай, если кто-нибудь еще столкнется с тем же вопросом.

Обойти это невозможно. Вы должны использовать, чтобы остановить событие от переполнения DOM. stopPropagation() Другой вариант — использовать noClick и для родительского элемента.

noClick отключает только открытие селектора файлов при нажатии на узел dropzone. Это не предотвращает появление пузырьков события.

Единственное, что мы можем сделать, это предоставить noClickBubbling опцию, которая вызывает stopPropagation() , но пользователь уже может это сделать.