Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

145
Views
Returned array evaluated later from async Firestore calls doesn't update in React

It seems "images" array is first empty and the elements are added later when data is fetched from firestore - but the React state won't update, so no image is displayed, although I used await everywhere possible.

useEffect(() => {
    async function getAllImages() {
      const images = await imageStorage.downloadAllImages(true);
// images is first empty and then populated after the html has been rendered
      setImages(images);
    }
   
      getAllImages();
    
  }, []);

display images:

const handleGetImages = (images) => {
    console.log("images", images); // image is first empty and then populated after the html has been rendered
    return images.map((imageData) => {
      return (
        <Grid.Column key={imageData.url}>
          <span class="image left">
            <img src={imageData.url} style={styles.image} alt="" />
          </span>
        </Grid.Column>
      );
    });
  };

imageStorage.js

export async function downloadAllImages(thumbnail) {
  const imageRef = collection(db, "images");
  console.log("hi");
  var images = [];

  const q = query(imageRef, orderBy("date", "desc"), limit(10));
  const querySnapshot = await getDocs(q);

  querySnapshot.forEach(async (doc) => {
    var imagePath = doc.data().ref; // image/task/...
    if (thumbnail) imagePath = imagePath.replace("images", "thumbnails");
    // GET metadata of the image
    const imageRef = ref(storage, imagePath);

    // GET [imagePrefix] URL
    const url = await getDownloadURL(imageRef);
    const fullMetadata = await getMetadata(imageRef);

    images.push({
      path: imagePath,
      url: url,
      metadata: fullMetadata.customMetadata,
    });
  });

  return images;
}

Any way to fix this? Thanks!

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

Your code is close. Array.prototype.forEach is synchronous though. I suspect your downloadAllImages function isn't waiting for the loop callbacks to complete and returns the images array not populated yet.

Refactor the logic to create an array of Promises (the async callback functions) and await Promise.all them, then you'll have a populated array of images to return.

export async function downloadAllImages(thumbnail) {
  const imageRef = collection(db, "images");

  const q = query(imageRef, orderBy("date", "desc"), limit(10));
  const querySnapshot = await getDocs(q);

  // Map querySnapshot docs to array of async functions (Promises)
  const imageRequests = querySnapshot.docs.map(async (doc) => {
    const imagePath = doc.data().ref; // image/task/...
    if (thumbnail) imagePath = imagePath.replace("images", "thumbnails");
    // GET metadata of the image
    const imageRef = ref(storage, imagePath);

    // GET [imagePrefix] URL
    const url = await getDownloadURL(imageRef);
    const fullMetadata = await getMetadata(imageRef);

    // Return image objects
    return {
      path: imagePath,
      url: url,
      metadata: fullMetadata.customMetadata,
    };
  });

  // Return array of resolved promises (i.e. the image objects)
  return Promise.all(imageRequests);
}
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!