我仍然对React钩子不熟悉,并且我尝试修改some code以仅允许在Firebase中对用户进行身份验证的情况下访问某些路由。同时,我希望用户键入不存在的路径,将其重定向到首页。而且,如果他在注销时尝试访问其中一条受保护的路由,则还应该将其重定向到家庭。这是我的App.js的样子:
import React, {Fragment, lazy, Suspense, useState, useEffect} from "react";
import {CssBaseline, MuiThemeProvider} from "@material-ui/core";
import {BrowserRouter, Redirect, Route, Switch} from "react-router-dom";
import theme from "./theme";
import GlobalStyles from "./GlobalStyles";
import * as serviceWorker from "./serviceWorker";
import Pace from "./shared/components/Pace";
import Firebase from "./firebase";
import FirebaseContext from "./firebase-context";
const firebase = new Firebase();
const LoggedInComponent = lazy(() => import("./logged_in/components/Main"));
const LoggedOutComponent = lazy(() => import("./logged_out/components/Main"));
function onAuthStateChange(callback) {
return firebase.auth.onAuthStateChanged(user => {
if(user) {
callback({loggedIn: true});
} else {
callback({loggedIn: false});
}
});
}
function App() {
const [user, setUser] = useState({loggedIn: false});
useEffect(() => {
const unsubscribe = onAuthStateChange(setUser);
return () => {
unsubscribe();
}
}, [setUser]);
console.log("logged in?", user.loggedIn);
return (
<BrowserRouter>
<FirebaseContext.Provider value={firebase}>
<MuiThemeProvider theme={theme}>
<CssBaseline/>
<GlobalStyles/>
<Pace color={theme.palette.primary.light}/>
<Suspense fallback={<Fragment/>}>
<Switch>
{user.loggedIn && <Route path="/c" component={LoggedInComponent}/>}
<Route exact path="/" component={LoggedOutComponent}/>
<Redirect to="/"/>
</Switch>
</Suspense>
</MuiThemeProvider>
</FirebaseContext.Provider>
</BrowserRouter>
);
}
serviceWorker.register();
export default App;
我遇到的问题是,当我登录并进入主页时。如果我尝试在URL中添加“ / c”以获取受保护的部分,则会被重定向回主页,就像我没有登录一样。
当我登录后重新加载主页时,会收到2条控制台日志,其中一条说我没有登录,另一条说我是。而且我认为发生了什么事,就是在应用程序有机会呈现并看到我已登录之前,我已被重定向。这似乎可以由以下事实证实:如果我注释掉我的重定向,我可以进入{{ 1}}。但是后来我没有获得该重定向的其他好处。
我很难理解的是为什么/c
第一次呈现组件时为假。
答案 0 :(得分:0)
我想出了如何使用this third party library而不重新发明轮子(也不需要使用依赖疯狂的实验性React东西的ReactFire)来做到这一点。这是结果代码:
import React, { Fragment, Suspense, lazy, useContext } from "react";
import { MuiThemeProvider, CssBaseline } from "@material-ui/core";
import { Route, Switch, Redirect } from "react-router-dom";
import theme from "./theme";
import GlobalStyles from "./GlobalStyles";
import * as serviceWorker from "./serviceWorker";
import Pace from "./shared/components/Pace";
import {useAuthState} from "react-firebase-hooks/auth";
import FirebaseContext from "./firebase-context";
import LinearProgress from "@material-ui/core/LinearProgress";
const LoggedInComponent = lazy(() => import("./logged_in/components/Main"));
const LoggedOutComponent = lazy(() => import("./logged_out/components/Main"));
function App() {
const firebase = useContext(FirebaseContext);
const [user, initialising, error] = useAuthState(firebase.auth);
console.log("user", user);
console.log("initialising", initialising);
console.log("error", error);
return (
<MuiThemeProvider theme={theme}>
<CssBaseline />
<GlobalStyles />
<Pace color={theme.palette.primary.light} />
{initialising ? <LinearProgress/> :
<Suspense fallback={<Fragment />}>
<Switch>
{user && <Route path="/c">
<LoggedInComponent />
</Route>}
<Route exact path="/">
<LoggedOutComponent />
</Route>
<Redirect to="/"/>
</Switch>
</Suspense>}
</MuiThemeProvider>
);
}
serviceWorker.register();
export default App;
实际上,我必须延迟路由选择开关的显示,直到Firebase auth的钩子完成初始化为止。