简体   繁体   中英

Redirect user to protected route if user already logged in causes login page to re-render and display for sometime before redirection

I have a react + firebase application which has protected routes. I face issue if a logged in user accesses the login page. The issue is that the login page gets displayed for a second and then redirects to the home page ie protected route. I feel the issue is because the value retrieved from context in the login page to check if user is authenticated gets updated after the route is resolved. Can someone give me pointers on how should I fix this. Ideally I would not want the user to see the login page for sometime if the user is already authenticated.

//App.js
render() {
    return (
      <AuthProvider>
        <Router>
          <Switch>
            <PrivateRoute exact path="/" component={Home}></PrivateRoute>
            <Route exact path="/login" component={LoginPage}></Route>
            <Route exact path="/signup" component={SignUp}></Route>
          </Switch>
        </Router>
      </AuthProvider>

    );
  }
}

//AuthProvider
import React, { useEffect, useState } from "react"
import { fire } from "./Fire"

export const AuthContext = React.createContext();

//this component will maintain the current user throughout the app
export const AuthProvider = ({ children }) => {
    const [currentUser, setCurrentUser] = useState(null)

    //empty array as second arg to useEffect hook as we only want to trigger it once
    useEffect(() => {
        console.log("useEffect")
        fire.auth().onAuthStateChanged(setCurrentUser)
    }, [])

    return (
        <AuthContext.Provider value={{ currentUser }}>{children}</AuthContext.Provider>
    )
}

//PrivateRoute
const PrivateRoute = ({ component: RouteComponent, ...rest }) => {

    //useContext hook makes it very easy to retrieve the value
    const { currentUser } = useContext(AuthContext)
    return (
        <Route {...rest} render={
            routeProps => {
                console.log("currentUser" + currentUser);
                return !!currentUser ? (
                    <RouteComponent {...routeProps} />
                ) : (
                        <Redirect to={"/login"} />
                    )
            }

        } />
    )
}

//login
render() {
        if (this.props.context.currentUser)
            return <Redirect to="/" />
        return (
            <Login email={this.state.email} password={this.state.password} inputHandler={this.onInputChange} loginHandler={this.onLoginClick} />
        )
    }

You should probably add a loading check in your PrivateRoute file which will just show a Loading... or a loader if the user is not loaded yet. For that you will have to do some minor changes in your AuthProvider file and in PrivateRoute .

//PrivateRoute
const PrivateRoute = ({ component: RouteComponent, ...rest }) => {

    //useContext hook makes it very easy to retrieve the value
    const { currentUser } = useContext(AuthContext)
    return (
        <Route {...rest} render={
            routeProps => {
                console.log("currentUser" + currentUser);
                return !!currentUser ? (
                    <RouteComponent {...routeProps} />
                ) : currentUser === 'loading' ? <h1>Loading...</h1>
                  :(
                        <Redirect to={"/login"} />
                    )
            }

        } />
    )
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM