useContext全局更新useState变量异常:Login组件无法获取正确user值
问题原因
你遇到的问题是因为signInWithPopup完成后,立刻调用addToUsers时,AuthContext中的user还没完成更新。Firebase的onAuthStateChanged是异步回调,登录操作完成后,这个回调不会立刻执行,所以Login组件中从Context获取的user还是初始的空对象。
解决方案
方案一:直接使用登录返回的用户信息
不需要依赖Context的更新,直接从signInWithPopup的返回结果中拿到用户数据,传给addToUsers:
const googleSignIn = async() =>{ // 获取登录结果里的用户对象 const result = await signInWithPopup(auth, provider) const signedInUser = result.user; // 把用户对象传入addToUsers await addToUsers(signedInUser) navigate('/') } const addToUsers = async(user) =>{ console.log(user) // 用传入的user操作数据库 await setDoc(doc(db, 'users', user.uid), { displayName: user.displayName, photoURL : user.photoURL, }) }
方案二:监听Context中user的变化
通过useEffect监听Context里user的变化,当user更新为登录状态时,再执行addToUsers:
const Login = () => { const {user} = useContext(AuthContext) const navigate = useNavigate() // 标记是否已执行过数据库操作,避免重复触发 const [addedToDb, setAddedToDb] = useState(false) const googleSignIn = async() =>{ await signInWithPopup(auth, provider) navigate('/') } const addToUsers = async() =>{ console.log(user) await setDoc(doc(db, 'users', user.uid), { displayName: user.displayName, photoURL : user.photoURL, }) setAddedToDb(true) } // 监听user变化,当user存在且未执行过数据库操作时触发 useEffect(() => { if (user?.uid && !addedToDb) { addToUsers() } }, [user, addedToDb]) // ... 其余代码不变 }
额外优化:清理AuthContext中的订阅
你的AuthContext里的useEffect没有清理onAuthStateChanged的订阅,可能会导致内存泄漏,建议加上清理函数:
useEffect(() => { const unsub = onAuthStateChanged(auth, (user) => { setUser(user); console.log(user); }); // 组件卸载时取消订阅 return () => unsub(); }, [])
内容的提问来源于stack exchange,提问作者Het Patel
相关产品推荐
相关产品推荐

