skip to Main Content

I am working with React, and I have a component that gets data from Firebase, which is a list of movies the user has watched.

After getting that data, I loop through that individual movie and get data of the movie. This all happens when the component mount:

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

And getWatched is the function that gets all the data:

const getWatched = async () => {
  try {
    const snapShot = await getDocs(
      collection(db, "users", auth.currentUser.uid, "Watched")
    );
    let arr = [];
    snapShot.forEach((doc) => {
      arr.push(doc.data());
    });
    let w = [];
    arr.forEach((obj) => {
      let show = obj.show ? "movie" : "tv";
      console.log(obj.id);
      const link =
        "https://api.themoviedb.org/3/" +
        show +
        "/" +
        obj.id +
        "?api_key=" +
        process.env.REACT_APP_MOVIE_DB +
        "&language=en-US";
      fetch(link)
        .then((response) => response.json())
        .then((response) => w.push(response));
    });
    setWatched(w);
    console.log("Got Data");
  } catch (error) {
    console.log(error);
  }
};

And in the return, I am looping through watched and returning divs of the data I have got. I guess I am getting data late. So it is not showing me anything.

2

Answers


  1. Chosen as BEST ANSWER

    I am satisfied with Youssouf Oumar's answer. Here is another way I have also tried:

    const getWatched = async () => {
            try {
                const snapShot = await getDocs(collection(db, "users", auth.currentUser.uid, "Watched"));
                let arr = [];
                snapShot.forEach((doc) => {
                    arr.push(doc.data());
                })
                let w = [];
                arr.forEach((obj) => {
                    let show = obj.show ? "movie" : "tv";
                    const link = "https://api.themoviedb.org/3/" + show + "/" +
                        obj.id + "?api_key=" + process.env.REACT_APP_MOVIE_DB + "&language=en-US";
                    w.push(getData(link));
                });
                Promise.all(w)
                    .then(results => {
                        setWatched(results);
                    })
                    .catch((err) => console.log(err));
            } catch (error) {
                console.log(error);
            }
        }
    

    The main idea here, as Youssouf Oumar said, is using Promise.all.


  2. It’s because setWatched(w) is being called before the promises resolve. A solution to this is to use a Promise.all() like so:

    const getWatched = async () => {
      const innerFetch = async (link) => {
        const res = await fetch(link);
        const data = await res.json();
        return data;
      };
      try {
        const snapShot = await getDocs(
          collection(db, "users", auth.currentUser.uid, "Watched")
        );
        const arr = [];
        snapShot.forEach((doc) => {
          arr.push(doc.data());
        });
    
        const promises = arr.map((obj) => {
          let show = obj.show ? "movie" : "tv";
          console.log(obj.id);
          const link =
            "https://api.themoviedb.org/3/" +
            show +
            "/" +
            obj.id +
            "?api_key=" +
            process.env.REACT_APP_MOVIE_DB +
            "&language=en-US";
          return innerFetch(link);
        });
    
        const w = await Promise.all(promises);
        setWatched(w);
        console.log("Got Data");
      } catch (error) {
        console.log(error);
      }
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search