React-dropzone Multi Upload Files Combining with Additional Metadata

3.6k Views Asked by At

My goal is that create upload module like that: enter image description here

I want to upload multiple files with additional metadata. if file type is invoice i want to attach datepicker results too. otherwise only file and it's type. also, I want to remove each one with button.

I try to do that work with this code: https://codesandbox.io/s/multi-upload-problem-3ofbk?file=/src/App.js

I can't attach both 'type' and 'datepicker' properties to file, because I mapped them in another component for having different states for each input.

instead of getting array of objects like this:

 [
  {
    File: {
        path: 'file1.jpg',
        name: 'file1.jpg',
        lastModified: '123123123',
        lastModifiedDate: '231312312',
        size: 123123123,
        type: 'image/jpeg',
    },
    type_of_file: { docTypeSelect: 'invoice' },
    date_of_file: {
        invoiceDateInput: [
            'Tue Sep 07 2021 18:05:47 GMT+0400',
            'Fri Sep 10 2021 00:00:00 GMT+0400',
        ],
    },
 },
 {
    File: {
        path: 'file2.jpg',
        name: 'file2.jpg',
        lastModified: '123123123',
        lastModifiedDate: '231312312',
        size: 123123123,
        type: 'image/jpeg',
    },
    type_of_file: { docTypeSelect: 'other' },
    date_of_file: null,
 },
 {
    File: {
        path: 'file3.jpg',
        name: 'file3.jpg',
        lastModified: '123123123',
        lastModifiedDate: '231312312',
        size: 123123123,
        type: 'image/jpeg',
    },
    type_of_file: { docTypeSelect: 'image' },
    date_of_file: null,
 },
];

everything logging apart from each other. how can I solve this problem and log everything as one array before I send it to backend? My mind is totally confused with this problem :/ thank you in advance.

1

There are 1 best solutions below

1
Ravi L On

I had a chance to click through your code, and it seems that the complexity is because the FileList component is split from your Dropzone Component, and it's a little wonky to try and merge the data from the two components, even though they have overlapping data.

If possible, I'd consider rearchitecting as one component. Here's some draft code of how I might go about it.


const App.tsx = () =>{

return <FileList onFilesChanged=((listOfAllFiles) => console.log(listOfAllFiles)) />

}


const FileList = (onFilesChanged) =>{

// regular File Objects
const [uploadedFiles, setUploadedFiles] = useState([]);

// your file metadata as a map
const [fileDetailsList, uploadedFiles] = useState({});

const onDropDownChange = (fileId, value) => {
 // add the metadata in your map
 fileDetailsList[fileId].dropdownValue = value;
}

const onFinalUpload = () => {
  const allFiles = [];
  for(const file of files){
   // get the metadata from the map
   const metadata = fileDetailsList[file.id];
   const fileDetails = {file, ...metadata}

   // push the larger object
   allFiles.push(fileDetails);
  }

  // notify the parent component with all of our merged changes
  onFilesChanged(allFiles)

}

return (
<div>
{/* React dropzone code*/}
<input type="file" onFileUpload=((file)=>setUploadedFiles(uploadedFiles.concat(file)))/>

<uploadedFiles.map((file)=>{
<p>{file.name} </p>
<dropdown onDropdownChange=(file)/>
})

<Button onClick={onFinalUpload}/>

</div>
)


}