React中路由器,重定向和身份验证上下文的问题

I am still new to React hooks, and I am trying to adapt some code to only allow access to some routes if the user is authenticated in Firebase. And at the same time, I want the user to be redirected to home if he types a path that does not exist. And if he is trying to access one of the protected routes while being logged out, he should also be redirected to home. Here is what my App.js looks like:

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”以获取受保护的部分,则会被重定向回主页,就像我没有登录一样。

When I reload the home page while I'm logged in, I get 2 console logs, one that says I'm not logged in and once that says I am. And I think what is happening is that I get redirected before the App has a chance to render and see that I am logged in. Which seems to be confirmed by the fact that, if I comment out my Redirect, I can get to /c. But then I don't get the other benefits of that Redirect.

What I have trouble understanding is why user.loggedIn is false the first time the component is rendered.

评论