Reputation: 2270
The reader.onloadend calls a async function addData and reader.onloadend is in a loop.
const uploadFiles = () => {
console.log(acceptedFiles)
setLoading(true)
console.log(loading)
let i = 0
let l = acceptedFiles.length
for (i = 0; i < l; i++) {
let file = acceptedFiles[i]
const reader = new window.FileReader()
reader.readAsArrayBuffer(file)
reader.onloadend = () => {
let buffer = Buffer(reader.result)
console.log(buffer)
addData(file.path, buffer)
}
}
}
This is my async function addData
async function addData(name, buffer) {
const file = await myfunction()
}
I want to call setLoading(false) after all the async addData in the loop has been called. The onClick function doesn't work, loading is set to false when I click the button before all the async function is done.
const [loading, setLoading] = useState(false)
<button onClick={() => {
uploadFiles()
setLoading(false)
}}
disabled={loading}
>
Upvotes: 4
Views: 538
Reputation: 207501
Using promises you can know when all of the files have been read. Basic idea below
const uploadFiles = (evt) => {
// set loading to true;
const acceptedFiles = [...evt.target.files];
// Create a map of promises that will resolve when file is read
const readerPromises = acceptedFiles.map(file => {
return new Promise(resolve => {
const reader = new window.FileReader()
reader.readAsArrayBuffer(file)
reader.onloadend = () => {
console.log(file);
let buffer = reader; // Buffer(reader.result)
resolve([file.name, buffer])
}
});
});
// Detects when all of the promises are fully loaded
Promise.all(readerPromises).then(results => {
console.log(results);
// set loading to false;
});
};
<input type="file" multiple onchange="uploadFiles(event)" />
Upvotes: 5