Javascript 我如何在我的用户上下文中尝试使用onSnapshot?我想获得通知的实时更新(如facebook等)

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信息

我正在尝试从firebase获取实时通知或用户配置文件更新。我知道我需要使用
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>
  );
}