I am learning to react js with typescript. The function I wrote uploads the images into firebase when the action submits button is clicked and it returns an array of URLs. Everything works fine but it takes a lot of time. In the if statement, I do not want to go to the if statement until the upload is complete since I need to put the URLs array into the product object. I have used promises but it is not working while the success state is true.
If you want you can see the live code: https://codesandbox.io/s/eloquent-pine-tdv3wf?file=/src/AddProduct.tsx:1864-2218
This is the function that will set the state of the URLs into an array. Also, I have created promises after the success it will set true into the setSuccess state.
//States
const [success, setSuccess] = useState<boolean>(false)
const [images, setImages] = useState<any>([])
const [URLs, setURLs] = useState<any>([])
const uploadFiles = (files: any) => {
const promises: any = []
files.map((file: any) => {
const sotrageRef = ref(storage, `files/${file.name}`);
const uploadTask = uploadBytesResumable(sotrageRef, file);
promises.push(uploadTask)
uploadTask.on(
"state_changed",
(snapshot: any) => {
const prog = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgress(prog);
},
(error: any) => console.log(error),
async () => {
await getDownloadURL(uploadTask.snapshot.ref).then((downloadURLs: any) => {
setURLs((prevState: any) => [...prevState, downloadURLs]) // set the URLs into the URLs state
console.log("File available at", downloadURLs);
});
}
);
})
Promise.all(promises)
.then(() => setSuccess(true))
.then(err => console.log(err))
};
After clicking on submit action button this handleProductSubmit function will call and then it will call the uploadfiles function to set the uploaded files URLs into an array. If the success state is true then it will go to the next step for adding the URLs into my product data. The problem is it does not go to the next step while if statement condition is true
const handleProductSubmit = (e: any) => {
uploadFiles(images)
if (success) {
const newProductValue = { ...productValue, URLs }
console.log(newProductValue, 'newProductValue');
}
e.preventDefault()
}
CodePudding user response:
uploadFiles
is asynchronous, so you need to wait until everything is finished there before continuing:
const handleProductSubmit = async (e: any) => {
e.preventDefault()
const uploadWasSuccessful = await uploadFiles(images)
if (uploadWasSuccessful) {
const newProductValue = { ...productValue, URLs }
console.log(newProductValue, 'newProductValue');
}
}
Then change uploadFiles
to return the result instead of setting state (unless you need that state in other places, in which case both set the state and return the value):
const uploadFiles = async (files: any) => {
// ... snip ...
try {
await Promise.all(promises);
setSuccess(true);
return true;
} catch (e) {
console.error(e);
return false;
}
}
CodePudding user response:
In handleProductSubmit
after the uploadFiles
function, loop untill success == false && uploadFilesHasFinished == false
and in uploadFiles
output the variable at the end of the function and set uploadFilesHasFinished
to the output recieved.