Javascript 我如何在我的用户上下文中尝试使用onSnapshot?我想获得通知的实时更新(如facebook等)
我正在尝试从firebase获取实时通知或用户配置文件更新。我知道我需要使用Javascript 我如何在我的用户上下文中尝试使用onSnapshot?我想获得通知的实时更新(如facebook等),javascript,reactjs,firebase,google-cloud-firestore,react-hooks,Javascript,Reactjs,Firebase,Google Cloud Firestore,React Hooks,我正在尝试从firebase获取实时通知或用户配置文件更新。我知道我需要使用onSnapshot,但是,我以前尝试过,但没有取消订阅。如果您以另一个用户的身份注销并登录,它有时会获取以前登录的用户的配置文件数据,这是一个可怕的错误 所以基本上我有两个上下文提供者: AuthProvider(存储(currentUser)身份验证电子邮件、uid等) UserProvider(存储(userData)firestore数据,如个人资料图片、用户名、名字、姓氏等) 我如何才能订阅userData信息
onSnapshot
,但是,我以前尝试过,但没有取消订阅。如果您以另一个用户的身份注销并登录,它有时会获取以前登录的用户的配置文件数据,这是一个可怕的错误
所以基本上我有两个上下文提供者:
AuthProvider(存储(currentUser
)身份验证电子邮件、uid等)
UserProvider(存储(userData
)firestore数据,如个人资料图片、用户名、名字、姓氏等)
我如何才能订阅userData
信息,但在身份验证状态更改时确保它取消订阅?因为我每次尝试都失败了
授权提供者:
提前感谢您强>
因此,当前,当我的userAuth中的useEffect导致我有时以其他用户身份登录时:
import { auth, db } from "../firebase";
import { getUserByUserId } from "../services/firebase";
import { useAuth } from "./AuthContext";
const UserContext = React.createContext();
export function useUser() {
return useContext(UserContext);
}
export function UserProvider({ children }) {
const { currentUser } = useAuth();
const [userData, setUserData] = useState();
const [loading, setLoading] = useState(true);
//THIS USE EFFECT LISTENS TO SNAPSHOT DATA--------
useEffect(async () => {
let usersnapshot;
if (currentUser) {
usersnapshot = db.collection("users").doc(currentUser.uid);
usersnapshot.onSnapshot((doc) => {
setUserData(doc.data());
setLoading(false);
});
} else {
setLoading(false);
setUserData();
return usersnapshot;
}
}, [currentUser]);
//--------------------------
const value = {
userData,
};
return (
<UserContext.Provider value={value}>
{!loading && children}
</UserContext.Provider>
);
}
从“./firebase”导入{auth,db};
从“./services/firebase”导入{getUserByUserId};
从“/AuthContext”导入{useAuth};
const UserContext=React.createContext();
导出函数useUser(){
返回useContext(UserContext);
}
导出函数UserProvider({children}){
const{currentUser}=useAuth();
const[userData,setUserData]=useState();
const[loading,setLoading]=useState(true);
//此使用效果侦听快照数据--------
useffect(异步()=>{
让用户快照;
如果(当前用户){
usersnapshot=db.collection(“users”).doc(currentUser.uid);
usersnapshot.onSnapshot((doc)=>{
setUserData(doc.data());
设置加载(假);
});
}否则{
设置加载(假);
setUserData();
返回用户快照;
}
},[currentUser]);
//--------------------------
常量值={
用户数据,
};
返回(
{!正在加载(&children}
);
}
我建议在当前用户发生更改时分离侦听器。您能否尝试更改代码的这一部分:
useffect(异步()=>{
让用户快照;
让我们退订;
如果(当前用户){
usersnapshot=db.collection(“users”).doc(currentUser.uid);
unsubscribe=usersnapshot.onSnapshot((文档)=>{
setUserData(doc.data());
设置加载(假);
});
}否则{
设置加载(假);
setUserData();
返回用户快照;
}
退订;
},[currentUser]);
我们在这里所做的是保存对
useffect
中变量的unsubscribe
调用,并在currentUser
更改时调用它。每次用户更改时,都应该在快照上显示onSnapshot
。您能确认currentUser
在UserProvider
中的更改吗?@TarikHuber确实如此!我刚注销,currentUser现在为空。您能演示一下如何使用onSnapshot
?您的数据规则是什么样子的?用户不应能够从其他用户处获取数据。如果是这样的话,它看起来像是react状态管理中的一个bug。@TarikHuber当然!我现在就编辑我的帖子,谢谢你的帮助谢谢你的回复,不幸的是有时候还是会切换回原来的账号!你能告诉我到底发生了什么吗。
import React, { useContext, useState, useEffect } from "react";
import { getUserByUserId } from "../services/firebase";
import { useAuth } from "./AuthContext";
const UserContext = React.createContext();
export function useUser() {
return useContext(UserContext);
}
export function UserProvider({ children }) {
const { currentUser } = useAuth();
const [userData, setUserData] = useState();
const [loading, setLoading] = useState(true);
useEffect(async () => {
if (currentUser) {
const data = await getUserByUserId(currentUser.uid);
setUserData(data);
setLoading(false);
} else {
setUserData();
setLoading(false);
}
}, [currentUser]);
const value = {
userData,
};
return (
<UserContext.Provider value={value}>
{!loading && children}
</UserContext.Provider>
);
}
import { auth, db } from "../firebase";
// get user from the firestore where userId === userId (passed from the auth)
export async function getUserByUserId(userID) {
const result = await db.collection("users").doc(userID).get();
const user = result.data();
return user;
}
import { auth, db } from "../firebase";
import { getUserByUserId } from "../services/firebase";
import { useAuth } from "./AuthContext";
const UserContext = React.createContext();
export function useUser() {
return useContext(UserContext);
}
export function UserProvider({ children }) {
const { currentUser } = useAuth();
const [userData, setUserData] = useState();
const [loading, setLoading] = useState(true);
//THIS USE EFFECT LISTENS TO SNAPSHOT DATA--------
useEffect(async () => {
let usersnapshot;
if (currentUser) {
usersnapshot = db.collection("users").doc(currentUser.uid);
usersnapshot.onSnapshot((doc) => {
setUserData(doc.data());
setLoading(false);
});
} else {
setLoading(false);
setUserData();
return usersnapshot;
}
}, [currentUser]);
//--------------------------
const value = {
userData,
};
return (
<UserContext.Provider value={value}>
{!loading && children}
</UserContext.Provider>
);
}