Bueno, hice esta aplicación Biblioteca, donde un usuario puede iniciar sesión y agregar libros. Entonces, cuando un usuario inicia sesión en la aplicación, obtiene datos de una colección de firestore, genial. El problema existe cuando el usuario inicia sesión una vez, cierra sesión y luego vuelve a iniciar sesión sin actualizar la aplicación. Si el usuario hace esto dos veces, la busca dos veces, si lo hace tres veces, la busca tres veces. El código que se ejecuta varias veces es fetchBooks() , signInWithGoogle() solo se ejecuta una vez. Aquí está el código involucrado:
function signInWithGoogle(){ const provider = new firebase.auth.GoogleAuthProvider() auth.signInWithPopup(provider) .then(result => { // Create the new user document in firestore createNewUserDocument(result.user) // fetch feed data auth.onAuthStateChanged(user =>{ user? fetchBooks() : null }) }).catch(err => { console.log(err) }) signUpForm.reset() signUpModal.hide() signInForm.reset() signInModal.hide() } function fetchBooks() { const docRef = db.collection('users').doc(auth.currentUser.uid).collection('books') docRef.get().then(querySnapshot =>{ console.log(querySnapshot) querySnapshot.forEach(doc => { const data = doc.data() console.log(doc.data()); addCardToHTML(data.title, data.author, data.pages, data.description, data.read) }) }) }onAuthStateChanged es una suscripción que se activa cuando hay un cambio en el estado de autenticación del usuario.
Por lo tanto, se activará cuando inicie sesión, cuando cierre sesión, etc.
Entonces, lo ideal sería esperar hasta que el usuario inicie sesión y luego llamar a la función fetchBooks() , pero si continúa haciéndolo dentro del suscriptor, la función se activará cada vez que el suscriptor emita un nuevo valor.
Recomendaría comenzar con una reestructuración de su código para tener funciones que hagan cosas individuales. Ahora mismo, tienes una función signInWithGoogle . Esa función solo debe iniciar sesión del usuario con Google y devolver una promesa con el resultado de ese inicio de sesión. En su lugar, tiene que iniciar sesión en el usuario, buscar libros (que también está obteniendo libros Y modificando el DOM) y métodos de llamada en sus elementos de registro.
Reestructurar esto para tener alguna otra función de nivel superior probablemente lo ayudaría a manejar su problema más fácilmente. Específicamente, intente algo como esto:
function handleSignIn() { signInWithGoogle() .then(fetchBooks) .then(books => { books.forEach(book => addCardToHTML(...)) }) }Este es un buen comienzo porque ahora está claro lo que hace cada función individual. Ahora, para manejar su problema específico, asumiré que el problema al que se enfrenta es que ve que los libros se agregan varias veces. En ese caso, creo que lo que querrías que sucediera es que:
Si todas esas suposiciones son correctas, entonces su problema no estaría en el código que tiene, sino en la funcionalidad de cierre de sesión. Cuando el usuario cierra la sesión, debe agregar una función que elimine los libros del HTML. De esa manera, cuando vuelvan a iniciar sesión después de cerrar sesión, la función handleSignIn se activará nuevamente y la función addCardToHTML se ejecutará en una página HTML en blanco en lugar de una página que ya tiene las tarjetas.
Ejemplo:
function handleSignOut() { signOut() .then(clearBookCards) } function clearBookCards() { // Manipulate DOM to remove all of the card HTML nodes }