簡體   English   中英

如何在 React 應用程序中處理 Firebase onAuthStateChanged 並相應地路由用戶?

[英]How to handle Firebase onAuthStateChanged in a React app and route users accordingly?

我正在開發與 Firebase 集成的 React web 應用程序,我正在嘗試對我的用戶進行身份驗證。 如果用戶通過身份驗證,我已經設置了我的路由以顯示主頁組件,否則顯示登錄頁面。 但是,當我的應用程序首次加載時,它會顯示登錄頁面,它需要一兩秒鍾的時間來識別用戶實際上已經過身份驗證,然后切換到主頁。 它看起來很亂,我猜我對 onAuthStateChanged 的處理不夠好或不夠快。 在我的 App 組件中,我訂閱了一個 ReactObserver,它會在 auth state 發生更改時發出信號。 我該怎么做才能避免這種奇怪的行為?

我的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;
}

簡化版; 您可以使用登錄條件來加載數據;

  /**
  * loggedIn = undefined when loading
  * loggedIn = true if loading is finished and there is a user
  * loggedIn = flase if loading is finished and there is no user
  */
  const [loggedIn, setLoggedIn] = useState<boolean>();
  auth.onAuthStateChanged((user) => {
    if (user) {
      setLoggedIn(true);
    } else {
      setLoggedIn(false);
    }
  });

  useEffect(() => {
    if (loggedIn != undefined) {
      //do loggedIn stuff
    }
  }, [loggedIn]);

對於它可能關心的人來說,添加一個簡單的標志來表示身份驗證實際加載的時間為我解決了故障。 我還添加了受保護的路線(受這篇文章的啟發,我想我現在可以繼續我的項目了。

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>;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM