skip to Main Content

Hi everyone I have images locally uploaded and I want to upload them to Firebase Storage(which I am successfully uploading ) after that I get their downloadURL with getDownloadURL. since I am going to add multiple images to the collection I need to wait until all downloadURL’s are available and.then() I should be using addDoc() method to add new collection documents to firestore. But at the moment I am returning empty state.

const handleAdd = (e) => {
e.preventDefault();

storageImgsRef.map((imgStorageRef) => {
  const image = localImages[storageImgsRef.indexOf(imgStorageRef)];
  const uploadTask = uploadBytesResumable(imgStorageRef, image);

  uploadTask.on(
    "state_changed",
    (snapshot) => {},
    (error) => {
      console.log(error);
    },
    () => {
      getDownloadURL(uploadTask.snapshot.ref).then((url) => {
        setStorageImgsURL((prev) => [...prev, url]);
      });
    }
  );
});
addDoc(shopItemsCol, {
  description: description,
  discount: discount,
  price: price,
  title: title,
  images: [...storageImgsURL],
});

};

This code successfully adds a new document but with an empty image array. You can see the collection image below

Collection Img URL ;
https://drive.google.com/file/d/1XJWe2X0VdMDCXUuOL_u1ShyUEw9ARGvp/view?usp=sharing

2

Answers


  1. Chosen as BEST ANSWER

    Okay after half day here is the solution without setState.Basically, I create an empty array outside of the function and if the mapped array is not on the last index don't add anything to firestore just hold the image URLs with URLs.push(url) until the last index of the array we are mapping.

    const [storageImgsRef, setStorageImgsRef] = useState([]);// I couldn't make it work
     var URLs = [];
     const handleAdd = (e) => {
    e.preventDefault();
    
    storageImgsRef.map((imgStorageRef) => {
      const image = localImages[storageImgsRef.indexOf(imgStorageRef)];
      const uploadTask = uploadBytesResumable(imgStorageRef, image);
    
      uploadTask.on(
        "state_changed",
        (snapshot) => {},
        (error) => {
          console.log(error);
        },
        () => {
          getDownloadURL(uploadTask.snapshot.ref).then((url) => {
            // setStorageImgsURL((prev) => [...prev, url]);
            URLs.push(url);
            if (
              storageImgsRef.length - 1 ==
              storageImgsRef.indexOf(imgStorageRef)
            ) {
              addDoc(shopItemsCol, {
                description: description,
                discount: discount,
                price: price,
                title: title,
                images: [...URLs],
              });
            }
          });
        }
      );
    });
    

    };

    I would really appreciate it if anyone comes up with a state solution. Because with the same code state using, state returns an empty array. I don't know if this is something React should work on. Thanks all.


  2. I think the issue is you are setting the state and trying to consume that within the same iteration which means state will not yet have updated. To do this you can probably tweak your code as follows:

    const [statusDict, setStatusDict] = useState({});
    const statusValues = Object.values(statusDict);
    
    const handleAdd = (e) => {
      e.preventDefault();
      setStatusDict(Object.fromEntries(storageImgsRef.map(imgStorageRef => ([imgStorageRef, null]))
      storageImgsRef.map((imgStorageRef) => {
        const image = 
         localImages[storageImgsRef.indexOf(imgStorageRef)];
        const uploadTask = uploadBytesResumable(imgStorageRef, image);
    
      uploadTask.on(
        "state_changed",
        (snapshot) => {},
        (error) => {
          console.log(error);
        },
        () => {
          getDownloadURL(uploadTask.snapshot.ref).then((url) => {
           setStatusDict(prevStatus => ({...prevStatus, 
           [imgStorageRef]: url}))
        });
      });
    
    });
    };
    
    useEffect(()=> {
     if(statusValues.length && 
       statusValues.every(value => value !== null)){
        addDoc(shopItemsCol, {
          description: description,
          discount: discount,
          price: price,
          title: title,
          images: [...statusValues],
          });
          setStatusDict({})
        }
    
    }, [statusValues]);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search