Sam Scholefield
Sam Scholefield

Reputation: 1250

react-dropzone - accessing files added by click not drop

I am using the react-dropzone basic example (react-dropzone basic)

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

function Basic(props) {
  const {acceptedFiles, getRootProps, getInputProps} = useDropzone();

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

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

<Basic />

This is working as expected, until I use the click method to add a file. When adding a file using click the acceptedFiles do not register the file (I have added an onChange handler and event.target.files shows the file so it is defintely being added to the overall FileList).

Due to this I cannot display the file added by click details in the Files <ul> as I would with a dragged file. I assume the same would be true for fileRejections but I have not implemented it yet.

I hope I'm missing something obvious as I would assume that dropzone handles both drag and click behaviour?

Appreciate someone pointing me in the right direction if possible.

Upvotes: 3

Views: 13225

Answers (2)

gdh
gdh

Reputation: 13692

There is nothing wrong in your code. You just need to properly click on the div.

Just add bit of style to the drag and drop area so that the drop zone is clear to both drop as well as click.

working demo is here

export default function Basic(props) {
  const { acceptedFiles, getRootProps, getInputProps } = useDropzone();

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

  return (
    <section className="container">
      <div
        style={{
          cursor: "pointer",
          background: "gray",
          height: "200px",
          border: "2px dashed blue"
        }}
        {...getRootProps({ className: "dropzone" })}
      >
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>
      <aside>
        <h4>Files</h4>
        <ul>{files}</ul>
      </aside>
    </section>
  );
}

Upvotes: 1

Shubham Khatri
Shubham Khatri

Reputation: 281952

The above code handles both drag and drop, however it only gives you the latest added files and not the entire list of uploaded file.

To implement it correctly you can maintain a state and add an onDrop function to useDropzone in which you will append the files and update state

function Basic(props) {
  const [files, setFiles] = React.useState([]);
  const onDrop = React.useCallback(acceptedFiles => {
    setFiles(prev => [...prev, ...acceptedFiles]);
  }, []);
  const { getRootProps, getInputProps } = useDropzone({ onDrop });

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

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

Working demo

Upvotes: 3

Related Questions