首页 > 解决方案 > 当页面重新加载时,firebase.auth.currentUser 返回 null

问题描述

我正在尝试通过 react 对我的网络应用程序实施 firebase 身份验证。

登录/注销流程是这样的。

确认用户从SIGN-IN被重定向到HOME页面,并且在HOME页面点击“sign out”按钮的用户被重定向到SIGN-IN页面。

但是,问题是当经过身份验证的用户在主页重新加载页面时,用户被重定向到 SIGN-IN 页面,然后被重定向到 HOME 页面。

我认为经过身份验证的用户不会被重定向到登录页面。

我该如何解决这个问题?

我的代码如下:

import * as React from "react";
import { createContext, useContext } from "react";
import { firebase } from "../utils";

const FirebaseContext = createContext(firebase);

export const FirebaseProvider: React.FC = props => (
    <FirebaseContext.Provider value={firebase}>
        {props.children}
    </FirebaseContext.Provider>
);

export const useFirebase = () => useContext(FirebaseContext);

import * as React from "react";
import { Route, Switch } from "react-router-dom";
import * as routes from "./constants/routes";

import { FirebaseProvider } from "./contexts/FirebaseContext";
import { Home } from "./pages/Home";
import { SignIn } from "./pages/SignIn";

const App: React.FC = () => {
    return (
        <FirebaseProvider>
            <Switch>
                <Route exact={true} path={routes.SIGN_IN} component={SignIn} />
                <Route exact={true} path={routes.HOME} component={Home} />
            </Switch>
        </FirebaseProvider>
    );
};

export default App;
import { useState, useEffect } from "react";
import { User } from "firebase";


export const useAuthUser = (firebase: any) => {
    const [authUser, setAuthUser] = useState<User | null>(firebase.auth.currentUser);
    useEffect(() => {
        const unsubcribe = firebase.auth.onAuthStateChanged((user: User | null) => setAuthUser(user));
        unsubcribe();
    }, []);

    return authUser;
};
import * as React from "react";
import { useHistory } from "react-router-dom";

import { useFirebase } from "../../contexts/FirebaseContext";
import { useAuthUser } from "../../Hooks/AuthUserHook";
import * as routes from "../../constants/routes";
import { SignInForm } from "./SignInForm";


export const SignIn: React.FC = () => {
    const firebase = useFirebase();
    const authUser = useAuthUser(firebase);
    const history = useHistory();

    if (authUser) {
        history.push(routes.HOME);
    }

    return (
        <div>
            <h1>Sign in</h1>
            <SignInForm />
        </div>
    );
};
import * as React from "react";
import { useHistory } from "react-router-dom";
import { useFirebase } from "../../contexts/FirebaseContext";
import { useAuthUser } from "../../Hooks/AuthUserHook";

import * as routes from "../../constants/routes";

export const Home: React.FC = () => {
    const firebase = useFirebase();
    const authUser = useAuthUser(firebase);
    const history = useHistory();

    if (!authUser) {
        history.push(routes.SIGN_IN);
    }

    return (
        <div>
            <h2>Home Page</h2>
            <p>The Home Page is accessible by every signed in user.</p>
        </div>
    );
};

标签: reactjsfirebasefirebase-authentication

解决方案


页面加载后,Firebase SDK 会尝试从本地存储恢复用户的凭据。作为其中的一部分,它会与服务器检查用户的登录会话是否仍然有效,并且在此期间 currentUser 为空。然后,一旦登录会话恢复,它就会触发一个onAuthStateChanged具有新状态的事件。所以你需要挂钩来更新你的状态。

我通常处理这个问题的方法是从“登录”屏幕开始,然后当您在身份验证状态更改处理程序中获得有效用户时重定向到主屏幕。

一个额外的技巧是在用户之前进行身份验证时将您自己的标志存储在本地存储中,然后在页面加载时读取它。由于对该本地存储的访问是同步的,这意味着您可以在他们之前登录的情况下立即显示主屏幕。请记住,您的本地标志可能是错误的(因为这正是 Firebase 必须与服务器检查的原因),因此您应该能够处理导航回登录屏幕。


推荐阅读