-1

Hi I have exported using data (hawkers collection) using getDocs() from Firebase.

After that I put each hawker data as an object in an array called allStall as shown in the screenshot of the console log below.

enter image description here

Question 1 - How do I access each individual object in my allStall array. I try to use .map() to access each of it, but i am getting nothing.

Do note that I already have data inside my allStall array, see screenshot above. [Update] map doesn't work in code below because field is stallname not stallName. However, it needs to be async + await if using/call in/from other function.

Question 2 - Why is there [[Prototype]]: Array(0) in my allStall array

export /*Soln add async*/function getAllStall(){
  var allStall = [];
  try
  {
    /*Soln add await */getDocs(collection(db, "hawkers")).then((querySnapshot) =>
      {
        querySnapshot.forEach((doc) =>
          {
            var stall = doc.data();
            var name = stall.stallname;
            var category = stall.category;
            var description = stall.description;

            var stallData = {
              stallName:name,
              stallCategory:category,
              stallDescription:description
            };
            allStall.push(stallData);
});});

     console.log(allStall);

    //Unable to access individual object in Array of objects
    allStall.map(stall =>{console.log(stall.stallName);});}

  catch (e) {console.error("Error get all document: ", e);}

  return allStall;
}

In my main js file, i did the following:

useEffect(/*Soln add await*/() =>
    {
        getAllStall();
        /*Soln:replace the statement above with the code below
        const allStall = await getAllStall();
        allStall.map((stall)=>console.log(stall.stallname));
       */
    }
);
lonelearner
  • 1,637
  • 4
  • 14
  • 22
  • 2
    Does this answer your first question? [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – evolutionxbox Apr 25 '22 at 07:20
  • 1
    the length of the prototype object is 0, not this object. – mrtechtroid Apr 25 '22 at 07:21
  • 1
    `[[prototype]]` is the accessor property which gets the array's prototype object. https://stackoverflow.com/questions/7929159/does-a-new-object-in-javascript-have-a-prototype-property may help – evolutionxbox Apr 25 '22 at 07:26
  • Hi thanks for the comments, i don't quite understand your answer yet, is the issue because i wrongly access my objects or assign my objects in an array? – lonelearner Apr 25 '22 at 07:34
  • 2
    Which issue are you talking about? Your first question is pretty much answered by the question I linked. The second is nothing to worry about, and you can [read more about object prototypes here](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes) – evolutionxbox Apr 25 '22 at 07:36
  • Thanks for the further advices, I was referring to Question 1. From what I understand so far, seems like the issue is due to async fetching of data, hence data is empty while the sync code (console.log) is being implemented. However, i am able to retrieve the array of objects, so not sure if it is still async issue. If it is not async issue, it means I have issue on how to retrieve the individual objects. e.g. if i replace the console.log(allStall); =====> console.log(allStall[0].stallName); – lonelearner Apr 25 '22 at 07:43
  • 1
    *Do note that I am using promise/then syntax, so it is unlikely to be async* `promise` and `then` **is async**... – Liam Apr 25 '22 at 08:26
  • Yes it is, async. Thanks for clarifying that it is an async issue. Noted. – lonelearner Apr 25 '22 at 08:43

2 Answers2

2

You are getting nothing because allStall is empty since you are not waiting for the promise to be fullfilled

try this

export const getAllStall = () => getDocs(collection(db, "hawkers"))
       .then((querySnapshot) =>
           querySnapshot.map((doc) =>
              {
                const {stallName, category, description} =  doc.data();
            
            return  {
              stallName:name,
              stallCategory:category,
              stallDescription:description
            };
           
          });
      )

try to change use effect like this

useEffect(async () =>
    {
        const allStats = await getAllStall();
        console.log(allStats)
        allStats.forEach(console.log)
    }
);
Liam
  • 27,717
  • 28
  • 128
  • 190
R4ncid
  • 6,944
  • 1
  • 4
  • 18
  • 1
    @Liam You're right in principle but in this is case I used this mixed approach to avoid to change the code too much. – R4ncid Apr 25 '22 at 08:06
  • Hi thank you, allStall is not empty, see image above, console.log(allStalls). However, I do not know how to access the individual items inside allstalls. I have try allStalls[0], map and even foreach, but I still do not know how to access each individual items yet. – lonelearner Apr 25 '22 at 08:10
  • 1
    @lonelearner that `console.log` that you are referring to is the one in the code or one that you log by your own in the browser? – R4ncid Apr 25 '22 at 08:22
  • @Liam thanks for the advice, good that you noticed i am using promise/then syntax! That's why i am pretty sure it is not an async issue. But rather on how to access the data or poor structuring of data. – lonelearner Apr 25 '22 at 08:22
  • @R4nicd, good question, it is written in the code, above the map function. console.log(allStall); //Unable to access individual object in Array of objects allStall.map(stall =>{console.log(stall.stallName);}); – lonelearner Apr 25 '22 at 08:23
  • 1
    @lonelearner it **is** an async issue. – Liam Apr 25 '22 at 08:26
  • @liam, i see, as such, how should i correct my code? – lonelearner Apr 25 '22 at 08:26
  • 2
    @lonelearner try my latest edit and see if it works – R4ncid Apr 25 '22 at 08:27
  • @R4ncid Greatly appreciate your edits, hmm got some syntax error for getAllStall, and not sure why is it exporting as const instead of function. Also does not seems to be returning an array of objects. – lonelearner Apr 25 '22 at 08:40
  • 2
    @lonelearner it's a const holding an arrow function. I changed it so in this way so I can avoid to use return and curly braces. It return a Promise of an array of object since it is an async request – R4ncid Apr 25 '22 at 08:45
  • Thank you! Trying out the code, having some issue troubleshooting the syntax error in getAllStall. May need some help! – lonelearner Apr 25 '22 at 08:47
  • @R4ncid you rocks!!! Thanks for being the biggest contributor to my two solutions! I managed to figure it out and grow more as a developer!!! Deeply appreciated :) – lonelearner Apr 25 '22 at 09:14
0

A very big thanks to R4ncid, you have been an inspiration! And thank you all who commented below!

I managed to get it done with async and await. Latest update, I figure out what's wrong with my previous code too. I commented the solution in my question, which is adding the async to the function and await to getDocs.

Also map doesn't work in code above because field is stallname not stallName. However, it needs to be async + await if using in/calling from other function.

Helper function

export async function getAllStall(){

  const querySnapshot = await getDocs(collection(db, "hawkers"));

  var allStall = [];

  querySnapshot.forEach(doc =>
    {
      var stall = doc.data();
      var name = stall.stallname;
      var category = stall.category;
      var description = stall.description;

      var stallData = {
        stallName:name,
        stallCategory:category,
        stallDescription:description
      };

      allStall.push(stall);
   }
  );

  
  return allStall;
}

Main JS file

useEffect(async () =>
        {
            const allStall = await getAllStall();
            allStall.map((stall)=>console.log(stall.stallname));
        }
    );

Hurray enter image description here

lonelearner
  • 1,637
  • 4
  • 14
  • 22