【问题标题】:How to handle Firebase onAuthStateChanged in a React app and route users accordingly?如何在 React 应用程序中处理 Firebase onAuthStateChanged 并相应地路由用户?
【发布时间】:2021-06-30 17:40:30
【问题描述】:

我正在开发一个与 Firebase 集成的 React Web 应用程序,并且我正在尝试对我的用户进行身份验证。如果用户通过身份验证,我已经设置了我的路由以显示主页组件,否则显示登录页面。但是当我的应用程序第一次加载时,它会显示登录页面,它需要一两秒钟才能识别出用户实际上已经过身份验证,然后它会切换到主页。它看起来很乱,我猜我处理 onAuthStateChanged 的​​速度不够好或不够快。在我的 App 组件中,我订阅了一个 ReactObserver,它在身份验证状态发生变化时发出信号。我该怎么做才能避免这种奇怪的行为?

我的App.js

import {BrowserRouter, Route} from "react-router-dom";
import Home from "./Home";
import Login from "./Login";
import {loggedIn, firebaseObserver} from "../firebase";
import {useEffect, useState} from "react";

export default function App() {
    const [authenticated, setAuthenticated] = useState(loggedIn())

    useEffect(() => {
        firebaseObserver.subscribe('authStateChanged', data => {
            setAuthenticated(data);
        });
        return () => { firebaseObserver.unsubscribe('authStateChanged'); }
    }, []);

   return <BrowserRouter>
             <Route exact path="/" render={() => (authenticated ? <Home/> : <Login/>)} />
          </BrowserRouter>;
}

我的firebase.js

import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";
import ReactObserver from 'react-event-observer';

const firebaseConfig = {
    apiKey: ...,
    authDomain: ...,
    projectId: ...,
    storageBucket: ...,
    messagingSenderId: ...,
    appId: ...
};
firebase.initializeApp(firebaseConfig);
export const auth = firebase.auth();
export const firestore = firebase.firestore();
export const firebaseObserver = ReactObserver();

auth.onAuthStateChanged(function(user) {
    firebaseObserver.publish("authStateChanged", loggedIn())
});

export function loggedIn() {
    return !!auth.currentUser;
}

【问题讨论】:

    标签: reactjs firebase authentication react-router-dom observer-pattern


    【解决方案1】:

    它可能关心的人,添加一个简单的标志来说明何时实际加载身份验证解决了我的故障。我还添加了受保护的路线(受this article 启发,我想我现在可以继续我的项目了。

    App.js:

    import {BrowserRouter, Redirect, Route, Switch} from "react-router-dom";
    import Home from "./Home";
    import Login from "./Login";
    import {PrivateRoute} from "./PrivateRoute";
    import {loggedIn, firebaseObserver} from "../firebase";
    import {useEffect, useState} from "react";
    
    export default function App() {
        const [authenticated, setAuthenticated] = useState(loggedIn());
        const [isLoading, setIsLoading] = useState(true);
    
        useEffect(() => {
            firebaseObserver.subscribe('authStateChanged', data => {
                setAuthenticated(data);
                setIsLoading(false);
            });
            return () => { firebaseObserver.unsubscribe('authStateChanged'); }
        }, []);
    
        return isLoading ? <div/> :
            <BrowserRouter>
                <Switch>
                    <Route path="/" exact>
                        <Redirect to={authenticated ? "/home" : "/login"} />
                    </Route>
                    <PrivateRoute path="/home" exact
                                  component={Home}
                                  hasAccess={authenticated} />
                    <PrivateRoute path="/login" exact
                                  component={Login}
                                  hasAccess={!authenticated} />
                    <Route path="*">
                        <Redirect to={authenticated ? "/home" : "/login"} />
                    </Route>
                </Switch>
            </BrowserRouter>;
    }
    

    【讨论】:

      猜你喜欢
      • 2023-02-03
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多