我正在嘗試使用 Firebase 在我的 React 應用程式中設定用戶存在。每次用戶登錄應用程式時,我都會將其保存為一個users集合,并將其顯示為我的應用程式中的串列。
我需要顯示每個用戶的在線狀態,所以我使用 Firebase Realtime db 來更新 Firestore db,這是整個 AuthContext.js 檔案:
import React, { useState, useEffect, useContext, createContext } from "react";
import { db, rtdb } from "../firebase/firebase-config";
import {
getAuth,
signInWithPopup,
GoogleAuthProvider,
onAuthStateChanged,
signOut,
} from "firebase/auth";
import {
addDoc,
collection,
serverTimestamp,
getDocs,
query,
where,
limit,
updateDoc,
doc,
} from "firebase/firestore";
import { Redirect } from "react-router-dom";
import { ref as rtdbRef, set, onValue } from "firebase/database";
const authContext = createContext();
export function ProvideAuth({ children }) {
const auth = useProvideAuth();
return <authContext.Provider value={auth}>{children}</authContext.Provider>;
}
export const useAuth = () => {
return useContext(authContext);
};
function useProvideAuth() {
const [user, setUser] = useState(null);
const provider = new GoogleAuthProvider();
const auth = getAuth();
const [userLoading, setUserLoading] = useState(true);
const getUserByUid = async (uid) => {
let exists = false;
const querySnapshot = await getDocs(
query(collection(db, "users"), where("uid", "==", uid), limit(1))
);
querySnapshot.forEach(() => (exists = true));
return exists;
};
const persistUser = async (user) => {
const exists = await getUserByUid(user.uid);
if (!exists) {
await addDoc(collection(db, "users"), {
uid: user.uid,
displayName: user.displayName,
email: user.email,
photoURL: user.photoURL,
createdAt: serverTimestamp(),
updatedAt: null,
});
}
};
const logIn = () =>
signInWithPopup(auth, provider)
.then((result) => {
setUser(result.user);
persistUser(result.user);
})
.catch((err) => {
console.log(err);
});
const updateFirestoreUser = (user, status) => {
if (user) {
getDocs(
query(collection(db, "users"), where("uid", "==", user.uid), limit(1))
).then((querySnapshot) => {
querySnapshot.forEach((u) => {
updateDoc(doc(db, "users", u.id), {
online: status,
updatedAt: serverTimestamp(),
});
});
});
}
};
const logOut = () =>
signOut(auth)
.then(() => {
console.log("SIGNOUT", user);
updateFirestoreUser(user, false);
setUser(false);
return <Redirect to="/login" />;
})
.catch((err) => {
console.log(err);
});
function checkAuthStatus() {
return new Promise((resolve, reject) => {
try {
onAuthStateChanged(auth, async (user) => {
resolve(user);
setUser(user);
const connectedRef = rtdbRef(rtdb, ".info/connected");
const myConnectionsRef = rtdbRef(rtdb, `status`);
onValue(connectedRef, (snap) => {
if (snap.val() === true) {
console.log("TRUE");
if (user) {
set(myConnectionsRef, "connected");
updateFirestoreUser(user, true);
}
} else {
console.log("FALSE");
updateFirestoreUser(user, false);
}
//onDisconnect(myConnectionsRef)
//.set("disconnected")
//.then(() => {
// updateFirestoreUser(user, false);
//});
});
});
} catch {
reject("api failed");
setUser(false);
}
});
}
const getUser = async () => {
setUserLoading(true);
await checkAuthStatus();
setUserLoading(false);
};
useEffect(() => {
getUser();
}, []);
return {
user,
logIn,
logOut,
userLoading,
};
}
當我登錄和注銷時online,users集合中的欄位會更新,但當我關閉瀏覽器選項卡時不會更新,當我取消注釋這部分時它有點作業:
onDisconnect(myConnectionsRef)
.set("disconnected")
.then(() => {
updateFirestoreUser(user, false);
});
但是更改僅反映在實時資料庫中,Firestore 資料庫users集合中沒有更改,字串“disconnected”被添加到實時資料庫中,但用戶條目中沒有任何更改,我想在then()方法中更新。
被卡在這里2天了,我不知道我做錯了什么,我只需要該online欄位true是打開應用程式和用戶登錄的時間,以及false用戶注銷或關閉應用程式的時間在瀏覽器中。
uj5u.com熱心網友回復:
通過遵循您鏈接的檔案中的在線狀態系統,您將在實時資料庫中獲取在線狀態資訊。
要將這些資訊匯入 Firestore,您需要實作一個在實時資料庫寫入中觸發的 Cloud Functions 函式,如有關在 Firestore上實作在線狀態的檔案中更新 Firestore中的在線狀態資訊部分中所示。這是在 Firestore 中獲取在線狀態資訊的唯一方法,因為該資料庫沒有onDisconnect構建在線狀態系統所需的任何類似功能。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/365996.html
