如何在 React 应用程序中处理 Firebase onAuthStateChanged 并相应地路由用户?
How to handle Firebase onAuthStateChanged in a React app and route users accordingly?
我正在开发一个与 Firebase 集成的 React 网络应用程序,我正在尝试对我的用户进行身份验证。如果用户通过身份验证,我已经设置了我的路由以显示主页组件,否则显示登录页面。但是,当我的应用程序首次加载时,它会显示登录页面,它需要一两秒钟的时间来识别用户实际上已经过身份验证,然后切换到主页。它看起来很乱,我猜我对 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;
}
对于可能关心的人,添加一个简单的标志以指示何时实际加载身份验证解决了我的故障。我还添加了受保护的路由(受 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>;
}
我正在开发一个与 Firebase 集成的 React 网络应用程序,我正在尝试对我的用户进行身份验证。如果用户通过身份验证,我已经设置了我的路由以显示主页组件,否则显示登录页面。但是,当我的应用程序首次加载时,它会显示登录页面,它需要一两秒钟的时间来识别用户实际上已经过身份验证,然后切换到主页。它看起来很乱,我猜我对 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;
}
对于可能关心的人,添加一个简单的标志以指示何时实际加载身份验证解决了我的故障。我还添加了受保护的路由(受 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>;
}