Reputation: 1185
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
Upvotes: 1
Views: 5205
Reputation: 239
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:
Upvotes: 3
Reputation: 996
Check this out, i have added comment below and fixed your issue: https://codesandbox.io/s/dry-wave-457ee?file=/src/App.js
import React, { useCallback, useState, Fragment } from "react";
import { useDropzone } from "react-dropzone";
import "./App.css";
export default function App() {
const [files, setFiles] = useState([]);
const onDrop = acceptedFiles => {
console.log(acceptedFiles);
const allFiles = [...files, ...acceptedFiles]; //save all files here
console.log(allFiles);
setFiles(allFiles);
};
const { getRootProps, getInputProps } = useDropzone({ onDrop });
return (
<Fragment>
<div {...getRootProps()} className="input-area">
{
<div>
<p className="input-text">Drop the files here ...</p>
<p> drop next file here </p>
</div>
}
<input {...getInputProps()} />
</div>
<div>
Files :
{files.map(file => (
<li>{file.path}</li>
))}
</div>
</Fragment>
);
}
Upvotes: 1