简体   繁体   中英

Can't make Firestore to get only docs from logged user id

I am an UX Designer and I'm pretty new to working with Firebase.

I've been trying to develop a system on webflow integrated with Firebase using JavaScript and the Firebase SDK to a personal project and got stuck with this problem.

I have managed to create the authentication system, the signup system and everything is working as it should.

However, when I try to fetch data from Firestore userdata collection, I am not being able to get the current user id and pass it to the WHERE string on my query.

If I run the query without the WHERE, it works perfectly, bringing me all the documents in the userdata collection, but when I try to do it only for a specific user, it fails.

I already tried a lot of things which I think wasn't the right method to do this, the JavaScript below was my last attempt. I think I'm just too new on this and can't understand how to pass the id variable into the query.

Here is the link to the project: https://poupei.webflow.io/ . Just click "Criar conta" to create an account, you can use a fake email and 6 digit password and then login.

  // Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.4.0/firebase-app.js";
import { getAuth, onAuthStateChanged, signOut } from "https://www.gstatic.com/firebasejs/9.4.0/firebase-auth.js";
import { getFirestore, collection, getDocs, query, where, doc } from "https://www.gstatic.com/firebasejs/9.4.0/firebase-firestore.js"


// TODO: Add SDKs for Firebase products that you want to use
  // https://firebase.google.com/docs/web/setup#available-libraries

  // Your web app's Firebase configuration
 const app = initializeApp({
    apiKey: "AIzaSyAZUIyxf4Lsw6D9JOzVuNslsGJ8gXkPBVY",
    authDomain: "poupei-app.firebaseapp.com",
    projectId: "poupei-app",
    storageBucket: "poupei-app.appspot.com",
    messagingSenderId: "837432279066",
    appId: "1:837432279066:web:119bc86e42fb87ac17d1a3"
});

  // Initialize Firebase
  const auth = getAuth()
  const db = getFirestore();
  onAuthStateChanged(auth, (user) => {
  if (user) {
    // User is signed in, see docs for a list of available properties
    // https://firebase.google.com/docs/reference/js/firebase.User
    const userID = user.id;
    console.log("Logged In");
    console.log(userID);
    // ...
  } else {
    // User is signed out
    window.location.replace("https://poupei.webflow.io/");
  }
});

const q = query(collection(db, "userdata"), where("id", "==", userID));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
  const docs = doc.data();
   document.getElementById('nome').innerHTML = docs.nome;
   document.getElementById('sobrenome').innerHTML = docs.sobrenome;
   document.getElementById('email').innerHTML = docs.email;
   document.getElementById('saldo').innerHTML = docs.saldo;
});

 document.getElementById('logoutBtn').addEventListener('click', function(){
  signOut(auth).then(() => {
  // Sign-out successful.
  window.location.replace("https://poupei.webflow.io/");
}).catch((error) => {
  // An error happened.
});
});

</script>

´´´

I think that the query doesn't know what userID is because you are declaring that variable inside authStateChange. Try to move the declaration of userID to global scope + add a console.log() before executing the query to see if the userID is set correctly. Or just put the code that performs the query inside the onAuthStateChanged code so that you can use the userID.

@Allennick has the cause of the problem correct in their answer, but the solution won't work.


Signing in to Firebase (as well as loading data from Firestore and most other modern cloud APIs) is an asynchronous operation. While the user is being signed in (or the data is being loaded) your main code continues to run. Then when the user is signed in, your callback code is executed.

It's easiest to see this flow by running in a debugger, or adding some logging:

console.log("Attaching auth state listener");
onAuthStateChanged(auth, (user) => {
  if (user) {
    console.log("Got user state");
  }
});

console.log("Starting database query");
const q = query(collection(db, "userdata"), where("id", "==", userID));
const querySnapshot = await getDocs(q);

When you run this code it logs:

Attaching auth state listener

Starting database query

Got user state

This is probably not the order you expected, but it perfectly explains why you're not getting the user data from the database: the query executes before the user is ever loaded.


The solution to this problem is always the same: any code that needs to react to the current user state, needs to be inside the onAuthStateChanged callback, be called from there, or otherwise synchronized.

The simplest fix is to move your database code into the callback, like this:

onAuthStateChanged(auth, (user) => {
  if (user) {
    const userID = user.id;

    // 👇 Now that the user us know, we can load their data
    const q = query(collection(db, "userdata"), where("id", "==", userID));
    const querySnapshot = await getDocs(q);
    querySnapshot.forEach((doc) => {
      // doc.data() is never undefined for query doc snapshots
      console.log(doc.id, " => ", doc.data());
      const docs = doc.data();
       document.getElementById('nome').innerHTML = docs.nome;
       document.getElementById('sobrenome').innerHTML = docs.sobrenome;
       document.getElementById('email').innerHTML = docs.email;
       document.getElementById('saldo').innerHTML = docs.saldo;
    });
    
    document.getElementById('logoutBtn').addEventListener('click', function(){
      signOut(auth).then(() => {
      // Sign-out successful.
      window.location.replace("https://poupei.webflow.io/");
    }).catch((error) => {
      // An error happened.
    });
  } else {
    // User is signed out
    window.location.replace("https://poupei.webflow.io/");
  }
});

Also see:

(Posted answer on behalf of the question author to move it to the answer space) .

Updating with the code that worked for me with the help of Frank. Thanks Frank!

onAuthStateChanged(auth, async (user) => {
  if (user) {
    const userID = user.email;
    console.log(userID);
const q = query(collection(db, "userdata"), where("email", "==", userID));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
  // doc.data() is never undefined for query doc snapshots
  console.log(doc.id, " => ", doc.data());
  const docs = doc.data();
   document.getElementById('nome').innerHTML = docs.nome;
   document.getElementById('sobrenome').innerHTML = docs.sobrenome;
   document.getElementById('email').innerHTML = docs.email;
   document.getElementById('saldo').innerHTML = docs.saldo;
   document.getElementById('meta').innerHTML = docs.objetivo;
 
   })
  } else {
   console.log("nada");
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM