skip to Main Content

I’m setting up a system that monitors users online with Snapshot. It evaluates any changes in the database and updates the front end, creating an array in this.players.

The problem is that I can’t access the array anywhere in the code. If I put console.log(this.players) the array appears, but if I try to access this.players[0] it returns "undefined".

I tried to create a global variable in the class, but I still can’t access jogadores. I created a method that returns a promise, it worked, but strangely after 30 minutes, it stopped working.

this.getDataFromFirestore = () => {
  return new Promise((resolve, reject) => {
    firebase
      .firestore()
      .collection("roleta")
      .doc(this.myId)
      .collection("jogadores")
      .onSnapshot((snapshot) => {
        snapshot.docChanges().forEach((change) => {
          if (change.type === "added") {
            const dadosDoJogador = change.doc.data();
            const nomeDoJogador = dadosDoJogador;
            this.jogadores.push(nomeDoJogador);
          }
          if (change.type === "modified") {
            // console.log("Modified city: ", change.doc.data());
          }
          if (change.type === "removed") {
            this.jogadores = this.jogadores.filter((v) => {
              return v.id != change.doc.data().id;
            });
          }
        });
        montarListaFront(this.jogadores, this.myId, this.myName);

      });


    resolve(this.jogadores);
  });
};

// Chamando a função que retorna a Promise
this.getDataFromFirestore().then((jogadores) => {
  console.log("funcionou xxxx");

  try {
    console.log(this.jogadores); // jogadores agora deve conter os dados atualizados
  } catch (error) {
    console.log("nao funcionou");
  }
});

2

Answers


  1. It seems like you’re encountering issues with accessing the this.players array in your code. One possible reason for this could be the context in which this is being used. Arrow functions (() => {}) don’t bind their own this value but inherit it from the containing scope. However, there are exceptions, particularly when dealing with class methods and asynchronous operations.

    Make sure this.myId and this.myName are properly initialized within your class as well. This structure ensures that this.players is accessed within the correct scope and should resolve the issue you’re facing.

    Login or Signup to reply.
  2. It’s not so much where you access the jogadores array, but when you access it. The code inside onSnapshot runs asynchronously (as it needs to read the data from the network or from disk) and when you resolve(this.jogadores) the data hasn’t been loaded yet.

    You can most easily see this with some well-placed log statements:

    console.log("Before starting onSnapshot");
    firebase
      .firestore()
      .collection("roleta")
      .doc(this.myId)
      .collection("jogadores")
      .onSnapshot((snapshot) => {
        console.log("Got data");
      });
    console.log("After starting onSnapshot");
    

    When you run this, the output is:

    Before starting onSnapshot
    After starting onSnapshot
    Got data

    This is probably not the order you expected the data in, but it explains why your code doesn’t work: you’re resolving the promise before the array has been populated.


    Since you are using a promise, the solution is to get the data rather than using onSnapshot. With that, you can simplify it to:

    this.getDataFromFirestore = async () => {
        const snapshot = await firebase
          .firestore()
          .collection("roleta")
          .doc(this.myId)
          .collection("jogadores")
          .get();
    
        snapshot.docChanges().forEach((change) => {
          if (change.type === "added") {
            const dadosDoJogador = change.doc.data();
            const nomeDoJogador = dadosDoJogador;
            this.jogadores.push(nomeDoJogador);
          }
          if (change.type === "modified") {
            // console.log("Modified city: ", change.doc.data());
          }
          if (change.type === "removed") {
            this.jogadores = this.jogadores.filter((v) => {
              return v.id != change.doc.data().id;
            });
          }
        });
        montarListaFront(this.jogadores, this.myId, this.myName);
    
        return this.jogadores;
    });
    

    Also see:

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search