Search code examples
reactjsreact-dropzone

Display file name using react dropzone


I'm trying to display a list of files which I will upload . I used react-dropzone library to drag and drop files. the dropped files are not stored in files array using the useState hook

import React, {  useState, Fragment } from "react";
import { useDropzone } from "react-dropzone";
import "./App.css";

export default function App() {
  const [files, setFiles] = useState([]);

  const onDrop = acceptedFiles => {
    setFiles(
      acceptedFiles.map(file => {
        
        return files.concat(file);
      })
    );
  };
  const { getRootProps, getInputProps } = useDropzone({ onDrop });

  return (
    <Fragment>
      <div {...getRootProps()} className="input-area">
        {
          <div>
            <p className="input-text">Drop the files here ...</p>
          </div>
        }
        <input {...getInputProps()} />
      </div>
      <div>
        Files :
        {
          files.map(file => <div>{file.path}   </div>)
        }
      </div>
    </Fragment>
  );
}

Here is the codesandbox link for the same https://codesandbox.io/s/hungry-margulis-ehgg2?file=/src/App.js:0-801


Solution

  • That's because you are using the useState Hook wrong. If you want to concat something to a state, you should use the functional parameter of setFiles. You can do it like this:

    const onDrop = acceptedFiles => {
        setFiles(files => files.concat(...acceptedFiles));
    };
    

    Otherwise you could do the following:

    const onDrop = useCallback(acceptedFiles => {
        setFiles(files.concat(...acceptedFiles));
    }, [files]);
    

    The useCallback Hook takes the files state as dependency and if that array changes, the method gets invalided from the cache :) But I would prefere the first example, because of the function you always have to correct state!

    Take a look here: