Home > Blockchain >  How will I setState in mapped array and use it in the same function
How will I setState in mapped array and use it in the same function

Time:10-14

Hi everyone I have images locally uploaded and I want to upload them to Firebase Storage(which I am successful in 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

CodePudding user response:

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.

CodePudding user response:

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();
  const statusDict = Object.fromEntries(storageImgsRef.map(
     ref => ([ref, 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) => {
       statusDict[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]);
  • Related