I am trying to upload multiple images on Firebase and get the URLs of each image and push them onto the database using api calls (With redux). I am trying to implement it using Promise.all() but the urls are being fetched asyncronously and the Promise.all() call is executed before the array state gets updated. Here is the code that might help you understand better.
..........
const [imgs,setImgs] = useState([])
const [urls,setUrls] = useState([]);
..........
//Code for setImg that will add all the files that are been selected!
..........
const uploadImages = async () => {
const promises = [];
imgs.map((image) => {
const imageRef = ref(storage, `Drives/${image.name + v4()}`);
const uploadTask = uploadBytesResumable(imageRef, image);
promises.push(uploadTask);
uploadTask.on(
"state_changed",
(snapshot) => {
const progress = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
// dispatch(fetchStart());
},
(error) => {
alert(error);
},
() => {
getDownloadURL(uploadTask.snapshot.ref).then((url) => {
console.log(url); // this is been shown after the promise.all is executed!!
setUrls((oldArray) => [...oldArray, url]); // This is not getting updated as expexted!!
});
}
);
});
Promise.all(promises) // Being executed before the urls state is updated hence is submitting a empty array!!
.then(() => {
toast.success("All images uploaded");
const FormatDate = moment(data.date).format("DD/MM/YYYY");
const { __v, ...rest } = data;
if (urls.length === 0) {
toast.error("Urls were not Pushed!!");
console.log(urls);
dispatch(clearState());
return 0;
}
const formData = {
...rest,
date: FormatDate,
driveImages: [...urls] ,// Or urls ---- This is showing empty.. But after some time urls is being updated!!
flags: {
isUploadImage: true,
},
};
dispatch(updateDrives(formData));
})
.catch((err) => toast.error(err));
};
I have mentioned appropriate comments in the code for better understanding.
The versions of firebase that I am using is "firebase": "^9.7.0".