skip to Main Content

I use react-dropzone to upload files.
When files are uploaded, they are stored in an array, which I use to list all items uploaded.

I added a button on the side of each li to delete the specific file from the array.

It works well, but opens a dialog to select a new file each time I delete one.

Is it possible to prevent this behaviour ?

Here is a simplified sandbox. The delete button must only console log, not open dialog : sandbox

Here is the simplified code :

import { useState } from "react";
import "./styles.css";
import Dropzone from "react-dropzone";
import * as React from "react";

export default function App() {
  const [files, setFiles] = useState([{ name: "test" }]);

  const handleDrop = () => {
    console.log("dropped");
  };

  return (
    <div className="App">
      <h1>React Typescript Tailwind CSS started</h1>

      <Dropzone onDrop={handleDrop}>
        {({ getRootProps, getInputProps }) => (
          <div style={{ border: "2px solid black", height: "100px" }}>
            <div>
              <div {...getRootProps()}>
                <input {...getInputProps()} />

                <button>Select a file</button>

                {files && files.length > 0 && (
                  <ul>
                    {files.map((file) => (
                      <li key={file.name} className="relative w-fit">
                        {file.name}
                        <button onClick={() => console.log("delete")}>
                          delete
                        </button>
                      </li>
                    ))}
                  </ul>
                )}
              </div>
            </div>
          </div>
        )}
      </Dropzone>
    </div>
  );
}

2

Answers


  1. See Using open() on Click

    If you bind a click event on an inner element and use open(), it will trigger a click on the root element too, resulting in the file dialog opening twice. To prevent this, use the noClick on the root:

    Choice 1. Use useDropzone({ noClick: true }) hook

    import { useState } from 'react';
    import { useDropzone } from 'react-dropzone';
    import * as React from 'react';
    
    export default function App() {
        const [files, setFiles] = useState([{ name: 'test' }]);
        const { getRootProps, getInputProps, open } = useDropzone({ noClick: true });
    
        return (
            <div className="App">
                <h1>React Typescript Tailwind CSS started</h1>
                <div style={{ border: '2px solid black', height: '100px' }}>
                    <div {...getRootProps()}>
                        <input {...getInputProps()} />
                        <button onClick={open}>Select a file</button>
                        {files && files.length > 0 && (
                            <ul>
                                {files.map((file) => (
                                    <li key={file.name} className="relative w-fit">
                                        {file.name}
                                        <button
                                            type="button"
                                            onClick={() => {
                                                console.log('delete');
                                            }}>
                                            delete
                                        </button>
                                    </li>
                                ))}
                            </ul>
                        )}
                    </div>
                </div>
            </div>
        );
    }
    

    codesandbox

    Choice 2. Pass noClick prop to Dropzone component.

    import { useState } from 'react';
    import Dropzone from 'react-dropzone';
    import * as React from 'react';
    
    export default function App() {
        const [files, setFiles] = useState([{ name: 'test' }]);
    
        const handleDrop = () => {
            console.log('dropped');
        };
    
        return (
            <div className="App">
                <h1>React Typescript Tailwind CSS started</h1>
    
                <Dropzone onDrop={handleDrop} noClick>
                    {({ getRootProps, getInputProps, open }) => (
                        <div style={{ border: '2px solid black', height: '100px' }}>
                            <div>
                                <div {...getRootProps()}>
                                    <input {...getInputProps()} />
                                    <button onClick={open}>Select a file</button>
                                    {files && files.length > 0 && (
                                        <ul>
                                            {files.map((file) => (
                                                <li key={file.name} className="relative w-fit">
                                                    {file.name}
                                                    <button onClick={() => console.log('delete')}>delete</button>
                                                </li>
                                            ))}
                                        </ul>
                                    )}
                                </div>
                            </div>
                        </div>
                    )}
                </Dropzone>
            </div>
        );
    }
    

    codesandbox

    Login or Signup to reply.
    1. Set noClick as true to prevent the dialog from opening every time someone clicks on any area inside the div

      const {getRootProps, getInputProps, open} = useDropzone({noClick: true})

    2. When you have to open the dialog use below:
      onClick={open}

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search