如何在 React 应用程序中处理 Firebase onAuthStateChanged 并相应地路由用户?

Posted

技术标签:

【中文标题】如何在 React 应用程序中处理 Firebase onAuthStateChanged 并相应地路由用户?【英文标题】:How to handle Firebase onAuthStateChanged in a React app and route users accordingly? 【发布时间】: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;

【问题讨论】:

【参考方案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>;

【讨论】:

以上是关于如何在 React 应用程序中处理 Firebase onAuthStateChanged 并相应地路由用户?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 firestoreConnect 指向 React-Redux-Firebase 中的嵌套集合?

使用 Laravel 托管 ReactJS

如何在同构 React + React 路由器应用程序中处理发布请求

如何在 Rails / Webpacker / React 应用程序中处理图像?

如何将来自不同组件的 firebase auth 和 Cloud Firestore 用作单个 Firebase 应用程序

如何在React中处理组件交互?