React - Firebase 使用单独的身份验证处理身份验证持久性 class

React - Firebase handling Auth persistence using a separate auth class

我正在构建一个使用简单登录功能的 React 应用程序。我只使用 google 登录,并调用 signInWithPopop 函数来处理它。我创建了一个单独的 class 来处理所有与身份验证相关的代码。在我网站的导航栏上,如果用户未登录,我有一个登录按钮,当用户登录后,该按钮会切换到个人资料按钮。

这就是我目前检查用户是否登录的方式(不工作):

console.log(authHandler.getUser());
const[loginState, setLogin] = useState(authHandler.getUser()? true : false);
return(
    <div className="navbar">
      <div className="nav-options">
        <NavItem name="About"></NavItem>
        <NavItem name="Listings"></NavItem>
        <NavItem name="Dashboard"></NavItem>
        {loginState ? <NavItem name="Profile"><DropDown loginState={setLogin}></DropDown></NavItem> : <NavItem name="Login" click={() => authHandler.signIn(setLogin)}></NavItem>}
      </div>
    </div>
  );

这就是我的 authHandler class:

import firebase from 'firebase';

export default class Auth{
    constructor(){
        var firebaseConfig = {
            ...
        };
        !firebase.apps.length? firebase.initializeApp(firebaseConfig) : firebase.app();
        firebase.analytics();
        this.provider = new firebase.auth.GoogleAuthProvider();
    }

    signIn(state){
        firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION).then(() => {
            return firebase.auth().signInWithPopup(this.provider).then((result) => {
                console.log("signed in " + result.user.uid);
                this.user = result.user
                state(true);
            }).catch((error) => {
                console.log(error.message);
            });
        }).catch((error) => {
            console.log(error.message);
        })
    }

    getUser(){
        return firebase.auth().currentUser;
    }

    logout(state){
        //TODO: logout of firebase
        state(false);
    }
}

我尝试在 firebase 上添加会话和本地持久性,但是当我刷新页面时,用户已注销。在像这样的单独 class 中,保持持久性的正确方法是什么?我正在尝试根据最佳实践构建此应用程序,以便正确拆分代码并维护安全性。

谢谢!

您应该使用 auth state observer 在用户登录状态发生变化时获得回调。当页面首次加载时,用户总是立即被视为已注销。回调将在用户令牌从持久性加载并验证后不久调用。使用此状态回调来确定要呈现的内容。

firebase.auth().onAuthStateChanged((user) => {
  if (user) {
    // User is signed in, see docs for a list of available properties
    // https://firebase.google.com/docs/reference/js/firebase.User
    var uid = user.uid;
    // ...
  } else {
    // User is signed out
    // ...
  }
});

您可能想要显示一个加载屏幕,直到第一个回调告诉您确定用户之前是否登录过或确实退出过。

我建议reading this for more information

我在 React 中实现身份验证状态的方式:

Auth.provider.tsx

import React, {
  FC,
  createContext,
  useContext,
  useEffect,
  useState,
} from 'react';
import { User, auth } from 'firebase/app';

interface AuthContext {
  user: User | null;
  loading: boolean;
}

const defaultAuthContext = { user: null, loading: false };

const AuthUserContext = createContext<AuthContext>({ ...defaultAuthContext });

export const AuthUserProvider: FC = ({ children }) => {
  const [authContext, setAuthContext] = useState<AuthContext>({
    user: null,
    loading: true,
  });

  useEffect(
    () =>
      auth().onAuthStateChanged((authUser) =>
        setAuthContext({ user: authUser, loading: false }),
      ),
    [],
  );

  return (
    <AuthUserContext.Provider value={authContext}>
      {children}
    </AuthUserContext.Provider>
  );
};

export const useAuthUser = () => useContext(AuthUserContext);

App.tsx

const App: React.FC = () => {
  return <AuthUserProvider>
    // anything
  </AuthUserProvider>;
}

anycomponent.tsx

const { user, loading } = useAuthUser();

return loading ? <Loader /> : !user ? <NotLogged /> : <Logged />;

您可以在 class 中实施观察者,但每次您需要您的用户时,您都应该实施一个 useEffect 观察用户。使其在提供程序中全局化使其更易于使用。

还有很多其他方法,但我认为这个是最容易使用的。