skip to Main Content

I created custom hook that gets images from my Firebase storage and returns it as an array of objects. Each object contains the name of the image file and the URL. With my current code, each object in the array contains the file name but the URL is a Promise object. Please check this picture enter image description here.

If I was to instead just return the URL only and not in an object, it works fine. It seems like it is not waiting for each Promise to resolve before setting the state? I am out of ideas! Thanks if you have any suggestions.


import { getStorage, ref, listAll, getDownloadURL } from "firebase/storage";
import { useState, useEffect } from "react";

export const useLogos = () => {
  const storage = getStorage();
  const listRef = ref(storage, "images/logos");
  const [logoList, setLogoList] = useState([]);

  useEffect(() => {
    listAll(listRef)
      .then((res) => {
        const promises = [];
        res.items.map((itemRef) => promises.push({name: itemRef.name, logoURL: getDownloadURL(itemRef)}));
        return Promise.all(promises)
      })
      .then((urlArray) => {
        setLogoList(urlArray);
      });
  }, []);

  return { logoList }
};

2

Answers


  1. You have to pass an array of Promises to Promise.all() but you pass an array of objects.

    The following refactoring should do the trick (untested):

    useEffect(() => {
        let fileNamesArray;
        listAll(listRef)
            .then((res) => {
                fileNamesArray = res.items.map((itemRef) => itemRef.name);
                const promises = res.items.map((itemRef) => getDownloadURL(itemRef));
                return Promise.all(promises)
            })
            .then((urlsArray) => {
                const objectsArray = urlsArray.map((elem, index) => ({ name: fileNamesArray[index], logoURL: elem }));
                setLogoList(objectsArray);
            });
    }, []);
    
    Login or Signup to reply.
  2. I found it: I was only return the first getDwnloadURL but I needed to map the promises.

    listAll(storageRef)
          .then((res) => {
            imageAppender = res.items.map((imgRef) => imgRef.name);
            const promises = res.items.map((imgRef) => getDownloadURL(imgRef));
            return Promise.all(promises);
          })
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search