Reputation: 928
I'm creating a picture converter where my JS code gets the file inputs from the user, sends it to my python back-end where they are converted and saved to a folder. Python then sends a response back to JS (react), which updates the state for each file individually as "converted" and re-renders the necessary components.
I have a for loop that sends individual POST requests for each file. This is fine until I want to create a .zip for the entire directory after all files have been converted. My problem lies there. My zip is always returned empty or with incomplete files.
// function which takes the file inputs from user
uploadBatch = async () => {
const files = this.getFilesFromInput();
const batch = Math.floor(Math.random() * 999999 + 100000);
for (let i = 0; i < files.length; i++) {
// sets the state which will then be updated
await this.setState(
{
files: [
...this.state.files,
{
// file state values
}
]
},
() => {
const formData = new FormData();
// appends stuff to form data to send to python
axios
.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
responsetype: 'json'
})
.then(response => {
// update the state for this particular file
});
}
);
}
return batch;
};
// function which zips the folder after files are converted
handleUpload = async e => {
e.preventDefault();
// shouldn't this next line wait for uploadBatch() to finish before
// proceeding?
const batch = await this.uploadBatch();
// this successfully zips my files, but it seems to run too soon
axios.post('/api/zip', { batch: batch }).then(response => {
console.log(response.data);
});
};
I have used async/await but I don't think I've used them well. I don't quite fundamentally understand this concept so an explanation would be greatly appreciated.
Upvotes: 1
Views: 2302
Reputation: 6289
Whenever you call setState()
, the component will re-render. You should ideally complete all your actions and call setState()
at the end.
Something like this should get things working for you
// function which takes the file inputs from user
uploadBatch = async () => {
const files = this.getFilesFromInput();
const batch = Math.floor(Math.random() * 999999 + 100000);
const files = [];
for (let i = 0; i < files.length; i++) {
const formData = new FormData();
// appends stuff to form data to send to python
const res =
await axios
.post('/api/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data'
},
responsetype: 'json'
});
files.push('push data into files arr');
}
return { files, batch };
};
// function which zips the folder after files are converted
handleUpload = async e => {
e.preventDefault();
// get batch and files to be uploaded and updated
const { files, batch } = await this.uploadBatch();
// this successfully zips my files, but it seems to run too soon
await axios.post('/api/zip', { batch: batch }).then(response => {
console.log(response.data);
});
// set the state after all actions are done
this.setState( { files: files });
};
Upvotes: 1