反应路由器专用路由异步使用效果

时间:2019-10-14 22:40:04

标签: reactjs authentication routes react-router

基本上,我遇到一个问题,如果有人要删除Cookie,我的路线将无法正常工作。我正在使用Auth0和React Router。

我不知道是为什么它跳过了if语句。不知道为什么不会被点击然后重定向到登录。

调试代码:

enter image description here

实际参考代码:

import React, { useEffect } from "react";
import history from "../history";
import { Route } from "react-router-dom";
import { useAuth0 } from '../auth/Auth';

const PrivateRoute = ({ component: Component, path, ...rest }) => {
debugger;
  const { authenticated } = useAuth0();
  useEffect(() => {
    const fn = async () => {
      console.log("authenticated", authenticated)
      if (!authenticated || authenticated === null) {
        history.replace('/login');
      }
    };
    fn();
  }, [authenticated, path]);

  const render = props => <Component {...props} />;

  return <Route path={path} render={render} {...rest} />;
};

export default PrivateRoute;

这是我App.js的精简版

import React, { useEffect } from "react";
import './App.scss';
import { Router, Route, Switch } from "react-router-dom";
import { Redirect } from "react-router";
import history from "./history";
import Home from "./scenes/Home/Home";
import Profile from "./scenes/Profile/Profile";
import SignUp from "./scenes/SignUp/SignUp";
import Login from "./scenes/SignUp/Login/Login";
import Dashboard from "./scenes/Dashboard/Dashboard";
import Account from "./scenes/Account/Account";
import Auth0Callback from "./scenes/Auth0Callback/Auth0Callback";
import { useAuth0 } from "./auth/Auth";
import PrivateRoute from "./components/PrivateRoute";

import PrivateRouteAuth from "./components/PrivateRouteAuth";
import NavBarMain from "./components/NavBarMain/NavBarMain";
import NavBarBasic from "./components/NavBarBasic/NavBarBasic";
import Footer from "./components/Footer/Footer";
import ScrollToTop from "./ScrollToTop";

// private route for main part of application
const NavRoute = ({ exact, path, component: Component }) => (
  <PrivateRoute
    exact={exact}
    path={path} render={(props) => (
      <>
        <NavBarMain />
        <Component {...props} />
        <Footer />
      </>
    )} />
)

// private route for signup since need basic navbar
const NavRouteSignUp = ({ exact, path, component: Component }) =>
  (
    <PrivateRouteAuth
      exact={exact}
      path={path} render={(props) =>
        (
          <>
            <NavBarBasic />
            <Component {...props} />
            <Footer />
          </>
        )} />
  )

function App() {

  const { renewSession, authenticated } = useAuth0();
  useEffect(() => {
    if (localStorage.getItem("auth") === "true") {
      renewSession();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);


  return (
    <div className="App">
      <Router history={history}>
        <ScrollToTop>
          <Switch>
            <Route exact path="/" render={() => (
              authenticated ? (
                <Route path="/" exact component={Home} /> 
              ) : (
                <Redirect to="/login" />
                )
            )} />
            {authenticated ? <NavRouteSignUp path="/signup" exact component={SignUp} /> : <NavRouteBase path="/signup" exact component={SignUp} />}
            {authenticated ? <NavRouteSignUp path="/login" exact component={Login} /> : <NavRouteBase path="/login" exact component={Login} styleName="noBorder" />}
            <Route path="/callback" render={(props) => {
              return <Auth0Callback {...props} />
            }} />
            <NavRoute exact component={Dashboard} path="/progress" />
            <NavRoute exact component={Profile} path="/profile" />
            <NavRoute exact component={Account} path="/account" />
          </Switch>
        </ScrollToTop>
      </Router>
    </div>
  );
}

export default App;

我的Auth.js与更新会话有关:

// logoout method removes all id's from local storage
  const logout = () => {
    console.log("the user is logging out");
    // Remove tokens and expiry time
    localStorage.removeItem('access_token')
    localStorage.removeItem('id_token')
    localStorage.removeItem('expires_at')
    localStorage.removeItem('user')
    localStorage.removeItem('auth')
    localStorage.removeItem('selection')
    setAuthenticated(null);
    setUser(null);
    history.push('/')
  }


  // method called once callback initiated
  const handleAuthentication = () => {
    console.log("auth0Client", auth0Client);
    if (typeof window !== 'undefined') {
      auth0Client.parseHash(async (err, authResult) => {
        if (authResult && authResult.accessToken && authResult.idToken) {
          console.log('inside the if authResult')
          await setSession(authResult);
          await howFarAlongIsUser();
        } else if (err) {
          console.log(err)
          return err;
        }
      })
    }
  }

  const isAuthenticated = () => {
    if (typeof localStorage !== 'undefined') {
      const expiresAt = JSON.parse(localStorage.getItem('expires_at'))
      // setAuthenticated(true);
      return new Date().getTime() < expiresAt
    } else {
      localStorage.setItem('auth', false)
      return false
    }
  }

  const setSession = async authResult => {
    const expiresAt = JSON.stringify(
      authResult.expiresIn * 1000 + new Date().getTime()
    )
    localStorage.setItem('access_token', authResult.accessToken)
    localStorage.setItem('id_token', authResult.idToken)
    localStorage.setItem('expires_at', expiresAt)
    localStorage.setItem('auth', true)

    setAuthenticated(true);
    await new Bluebird(function (resolve, reject) {
      auth0Client.client.userInfo(authResult.accessToken, (err, user) => {
        if (err) return reject(err)
        return resolve(user);
      })
    }).then(
      data => {
        localStorage.setItem('user', JSON.stringify(data))
        setUser(data);
        setAuthenticated(true);
      }
    )
  }

  const renewSession = async () => {

    auth0Client.checkSession({}, async (err, authResult) => {
      console.log("AUTH RESULT", authResult);
      if (authResult && authResult.accessToken && authResult.idToken) {
        await setSession(authResult);
      } else if (err) {
        console.log("loggin out inside renew session");
        console.log("error", err);
        logout();
      }
    });
  }

const getUser = () => {
    if (localStorage.getItem('user')) {
      return JSON.parse(localStorage.getItem('user'))
    }
  }

1 个答案:

答案 0 :(得分:0)

我能够通过完全删除useEffect并调用下面的if语句来修复它。我仍然对为什么顶级方法不起作用感到困惑。在删除本地存储之前,它工作正常。即使我看不到很多用户都在积极地这样做,但这种方式目前看来仍然可行:

const PrivateRoute = ({ component: Component, path, ...rest }) => {
  const { authenticated } = useAuth0();

  const render = props => <Component {...props} />;

  return (
    authenticated
      ? (<Route path={path} render={render} {...rest} />)
      : (<Redirect to={{ pathname: '/login' }} />));
};

export default PrivateRoute;

我在想,也许useEffect中的异步函数要等到它最初呈现后才能完成运行。