0

As described in comments between my code snippet, the asynchronicity is not working as expected. For each id, an object/item should return but it only returns one item since my async await isn't implemented properly. What could be a possible workaround?

Thanks in advance

useEffect(() => {
    axios.get('url-here').then((res) => {
      res.data.favProperties?.map((el) => {
        console.log(el) // this returns multitple id's of saved/liked items
        axios.get('url-here').then(async (r) => {
          if (r.data) {
            console.log(r.data) // Problem starts here
            // This returns the full object of the liked items
            // But only one object is returned, not every object for which an id was stored
            await storageRef
              .child(r.data.firebaseRef + '/' + r.data.images[0])
              .getDownloadURL()
              .then((url) => {
                // Here i need to fetch the image for each object
                console.log(url)
              })
              .catch((err) => console.log(err))
          }
        })
      })
    })
  }, [])
brunelli
  • 315
  • 2
  • 10
  • This seems like strange code to be called within the useEffect hook, perhaps more detail of the containing component will help to define what you are trying to do. – Scott Gnile Apr 11 '21 at 17:09
  • Adding to what @ScottGnile said above, you should probably use `async/await` since that's gonna improve the legibility of your code hence increasing maintenance and bugfixing. – Lars Apr 11 '21 at 17:10
  • Well I am using `async await` and tried lots of different things but nothing works. How can I implement `async await` correctly than please? – brunelli Apr 11 '21 at 17:13
  • @ScottGnile where and how should I make the calls than? – brunelli Apr 11 '21 at 17:16
  • @brunelli you can read about how to migrate your code to async/await here https://stackoverflow.com/a/55272812/1816108 – Lars Apr 11 '21 at 17:18
  • useEffect may be the right place to make an async call, however it's not clear what the effect of your call is going to have on your component. There is probably something in your component that is going to change... that something probably needs to be added to your useEffect dependency array. – Scott Gnile Apr 11 '21 at 17:24
  • Won't that create an infinite loop? – brunelli Apr 11 '21 at 17:26

1 Answers1

2

I think breaking down your operations into functions will prevent this Promise Hell. I would recommend using async await for these kinda operations. Also I was confused about the last part of console logging the download URL, by my guess you're trying to save all the download URLs for these liked items in an array.

    useEffect(() => {
      firstFunction();
    }, []);

    const firstFunction = async () => {
    const { data } = await axios.get("url-here");
    const favProperties = data.favProperties;
    const fetchedUrls = await Promise.all(
        favProperties?.map(async (el) => (
          await secondFunction(el.id) /** use el to pass some ID */
        ))
      );
    };
  
    const secondFunction = async (someId) => {
      /** your second URL must point to some ID (or some parameters) specific API otherwise
 running same op in a loop without variations doesn't make any sense */
      const { data } = await axios.get(`some-other-url/${someId}`);
      if (data) {
        console.log(data);
        const fetchedUrl = await storageThing(data);
        return fetchedUrl;
      }
    };
    
    const storageThing = async ({ firebaseRef, images }) => {
      try {
        const downloadURL = await storageRef
          .child(firebaseRef + "/" + images[0])
          .getDownloadURL();
        console.log(downloadURL);
         return downloadURL;
       } catch (error) {
         console.log(error);
         return '';
       }
     };
Siddhant
  • 93
  • 1
  • 5
  • thank you very much for your detailed answer. The thing is, my code was working all the time, but the result I expected was different because there was another problem (wrong `id's` were stored in the database so it was not possible to get multiple `objects` returned). Still, I can use this code in the future since it is a clear example of `async await`. Thanks again – brunelli Apr 13 '21 at 12:11