Here is my App.js in the react app:
import FileUpload from './components/file-upload'
const App = () => {
return (
<div>
<FileUpload />
</div>
);
}
export default App;
And here is my FileUpload component:
import Papa from "papaparse"
const FileUpload = (props) => {
return (
<main>
<div id="fileDrop"
onDragOver = {(e) => {
e.preventDefault()
}}
onDrop = {async(e) => {
e.preventDefault()
let dataArray = []
const data = await Object.values(e.dataTransfer.files).map( file => {
if (file.type === "text/tab-separated-values") {
const text = file.text()
text.then(text => {
const parsed = Papa.parse(text, {delimiter: "\t"})
parsed.data.forEach(row => {
dataArray.push(row)
return row
})
})
}
})
// console.log 1
console.log(data)
// console.log 2
console.log(dataArray)
// console.log 3
console.log(dataArray[0])
}}
>drag here</div>
</main>
)
}
export default FileUpload
The problem I'm running into is I can't seem to get access to the data from the .tsv file after I drop it. When I try to map over it and console.log the returned array (console.log 1), they just say undefined, and when I push it to dataArray and console.log that (console.log 2), I can click into it and all the data is there, but when I try to access an individual key (console.log 3), it says undefined again.
Am I using async/await correctly? Is it a problem with the file.text() promise? Thank you for your help!
Try looping over each file value first and filter
out any files that you don't need instead of using the if
statement. Then map
over each file and call file.text()
. This will return a Promise
for each file.
With Promise.all
you can wait for all of the promises to resolve before continueing. Now it makes sense to use await
as Promise.all
also returns a promise (Object.values
does not return a promise so awaiting it has no effect).
When all promises resolve you should end up with an array of texts. Loop over each text with flatMap
. The reason for doing this over a regular map
is that Papa.parse
returns an array of rows. flatMap
will flatten the array of arrays to a single array of rows, as seemed the intention with the code in the question.
const texts = await Promise.all(
Object.values(e.dataTransfer.files)
.filter(file => file.type === "text/tab-separated-values")
.map(file => file.text())
);
const dataArray = texts.flatMap(text => {
const parsed = Papa.parse(text, {delimiter: "\t"});
return parsed.data;
});