获取当前用户与Firestore和React不起作用

huangapple go评论124阅读模式
英文:

Get currentUser not working with firestore and react

问题

I've created a simple sign-up in which the user provides their name, bio, and profile picture. Currently, I am trying to display a logged-in user's data, however, I'm not having much luck doing so.

The issue here is that the data is not being retrieved (from the fact that my console only prints out "nothing"). I used the firestore documentation to create the getUser() function and am at a loss as to why it doesn't work.

import { useAuth } from "../../contexts/authContext";
import firebase from "firebase/compat/app";
import "firebase/compat/storage";
import "firebase/compat/firestore";
async function getUser() {
  const userRef = firestore
    .collection("users")
    .doc(firebase.auth().currentUser.uid);
  userRef.get().then(function (doc) {
    if (!doc.exists) { 
      console.log("nothing");
    } else {
      console.log("document", doc.data().name);
    }
  });
}

useEffect(() => {
  getUser();
}, [])

I've tried a lot of different methods, but none of which are giving me the results I want. I've attempted to use reactfire but I am in the process of debugging that as well. I've been researching this for days and feel clueless. Thanks for any input you can provide, I appreciate it.

英文:

I've created a simple sign-up in which the user provides their name, bio, and profile picture. Currently, I am trying to display a logged-in user's data, however, I'm not having much luck doing so.

The issue here is that the data is not being retrieved (from the fact that my console only prints out "nothing"). I used the firestore documentation to create the getUser() function and am at a loss as to why it doesn't work.

import { useAuth } from "../../contexts/authContext";
import firebase from "firebase/compat/app";
import "firebase/compat/storage";
import "firebase/compat/firestore";
  async function getUser() {
    const userRef = firestore
      .collection("users")
      .doc(firebase.auth().currentUser.uid);
    userRef.get().then(function (doc) {
      if (!doc.exists) { 
        console.log("nothing");
      } else {
        console.log("document", doc.data().name);
      }
    });
  }

  useEffect(() => {
    getUser();
  }, [])
  

I've tried a lot of different methods, but none of which are giving me the results I want. I've attempted to use reactfire but I am in the process of debugging that as well. I've been researching this for days and feel clueless. Thanks for any input you can provide, I appreciate it.

答案1

得分: 0

正如@samthecodingman建议的那样,我们不应该在新项目中使用紧凑的库。这里有一个示例,使用了新的模块化Firebase API。

我有一个基于上下文的示例:在App.tsx中,数据组件包装在AuthProvider中:

AuthProvider.tsx:

import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut,
  User,
} from "firebase/auth";
import { doc, getDoc } from "firebase/firestore";
import React from "react";
import { auth, db } from "../config/firebase";

type ContextType = {
  user: User | null;
  loading: boolean;
  login: (email: string, password: string) => Promise<User>;
  register: (email: string, password: string) => Promise<User>;
  logOut: () => Promise<void>;
  getUserData: () => Promise<void>;
};

const AuthContext = React.createContext({} as ContextType);

export function useAuth() {
  return React.useContext(AuthContext);
}

export const AuthProvider = ({ children }: React.PropsWithChildren) => {
  const [currentUser, setCurrentUser] = React.useState<User | null>(null);
  const [loading, setLoading] = React.useState(true);

  async function login(email: string, password: string) {
    const userCredential = await signInWithEmailAndPassword(auth, email, password);
    return userCredential.user;
  }

  async function register(email: string, password: string) {
    const userCredential = await createUserWithEmailAndPassword(auth, email, password);
    return userCredential.user;
  }

  async function getUserData() {
    if(auth.currentUser) {
      console.log("User: ", auth.currentUser);
      const userRef = doc(db, "users", auth.currentUser?.uid);
      const data = await getDoc(userRef);
      if(!data.exists()) console.log("Not Found");
      else console.log("User Data Found: ", data.data());
    } else console.log("User Not Found");
  }

  function logOut() {
    return signOut(auth);
  }

  React.useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged((user) => {
      setCurrentUser(user);
      setLoading(false);
    });

    return unsubscribe;
  }, []);

  const value = {
    user: currentUser,
    loading: loading,
    login: login,
    register: register,
    logOut: logOut,
    getUserData: getUserData
  };

  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  );
};

Data.tsx:

import { useEffect } from "react";
import { useAuth } from "./contexts/AuthProvider";

export default function Data() {
  const { login, getUserData, user, logOut, loading } = useAuth();

  async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    try {
      const user = await login("john@email.com", "password");
      console.log(user);
    } catch (err) {
      console.log(err);
    }
  }

  useEffect(() => {
    getData(); //如果用户已登录,这将打印用户数据;如果未登录,将打印未找到用户
  }, [user]);

  async function getData() {
    await getUserData();
  }

  return (
    <div>
      <form onSubmit={onSubmit}>
        <button type="submit" disabled={loading}>登录</button>
      </form>
      <br />
      {user && JSON.stringify(user)}
      <br />
      <button onClick={getUserData}>获取数据</button>
      <br />
      <button onClick={logOut}>注销</button>
    </div>
  );
};

要获取更多信息,您可以查看firebase文档以处理用户数据,还可以查看此存储库

英文:

As @samthecodingman suggested, we should not use compact libraries for new projects.Here’s one example with the new modular Firebase API.

I had one context based example : Here Data component is wrapped inside AuthProvider in App.tsx:
AuthProvider.tsx:

import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
User,
} from &quot;firebase/auth&quot;;
import { doc, getDoc } from &quot;firebase/firestore&quot;;
import React from &quot;react&quot;;
import { auth, db } from &quot;../config/firebase&quot;;
type ContextType = {
user: User | null;
loading: boolean;
login: (email: string, password: string) =&gt; Promise&lt;User&gt;;
register: (email: string, password: string) =&gt; Promise&lt;User&gt;;
logOut: () =&gt; Promise&lt;void&gt;;
getUserData: () =&gt; Promise&lt;void&gt;
};
const AuthContext = React.createContext({} as ContextType);
export function useAuth() {
return React.useContext(AuthContext);
}
export const AuthProvider = ({ children }: React.PropsWithChildren) =&gt; {
const [currentUser, setCurrentUser] = React.useState&lt;User | null&gt;(null);
const [loading, setLoading] = React.useState(true);
async function login(email: string, password: string) {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
return userCredential.user;
}
async function register(email: string, password: string) {
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
return userCredential.user;
}
async function getUserData() {
if(auth.currentUser) {
console.log(&quot;User: &quot;, auth.currentUser);
const userRef = doc(db, &quot;users&quot;, auth.currentUser?.uid);
const data = await getDoc(userRef);
if(!data.exists()) console.log(&quot;Not Found&quot;);
else console.log(&quot;User Data Found: &quot;, data.data());
}else console.log(&quot;User Not Found&quot;);
}
function logOut() {
return signOut(auth);
}
React.useEffect(() =&gt; {
const unsubscribe = auth.onAuthStateChanged((user) =&gt; {
setCurrentUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
const value = {
user: currentUser,
loading: loading,
login: login,
register: register,
logOut: logOut,
getUserData: getUserData
};
return (
&lt;AuthContext.Provider value={value}&gt;
{!loading &amp;&amp; children}
&lt;/AuthContext.Provider&gt;
);
};

Data.tsx:

import { useEffect } from &quot;react&quot;;
import { useAuth } from &quot;./contexts/AuthProvider&quot;;
export default function Data() {
const { login, getUserData, user, logOut, loading} = useAuth();
async function onSubmit(e: React.FormEvent&lt;HTMLFormElement&gt;) {
e.preventDefault();
try{
const user = await login(&quot;john@email.com&quot;, &quot;password&quot;);
console.log(user);
}catch(err){
console.log(err);
}
}
useEffect(() =&gt; {
getData(); //If user Logged in this will print UserData If not will print User Not Found
}, [user])
async function getData() {
await getUserData();
}
return (
&lt;div&gt;
&lt;form onSubmit={onSubmit}&gt;
&lt;button type=&quot;submit&quot; disabled={loading}&gt;Login&lt;/button&gt;
&lt;/form&gt;
&lt;br /&gt;
{user &amp;&amp; JSON.stringify(user)}
&lt;br /&gt;
&lt;button onClick={getUserData}&gt;Get Data&lt;/button&gt;
&lt;br /&gt;
&lt;button onClick={logOut}&gt;Logout&lt;/button&gt;
&lt;/div&gt;
);
};

For more information you can follow firebase documentation for handling users data and also take a look at this repo

huangapple
  • 本文由 发表于 2023年3月7日 11:21:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75657764.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定