React Router Private Route с проблемой проверки вызова API - PullRequest
0 голосов
/ 02 августа 2020

Я пытаюсь создать частный маршрут и проверить логин, я хочу выполнить вызов API, и он требует asyn c, но не могу использовать asyn c внутри компонента частного маршрута. Итак, попробовал использовать useEffect (), но он также показывает свои собственные ограничения со следующими проблемами:

  1. Когда сеанс не подтвержден, отображается страница входа, но сохраняется URL-адрес.
  2. Когда Пользователь уже вошел в систему и попытался получить доступ к странице входа, он никогда не входит в систему автоматически.

Мое простое требование - иметь два маршрута как Publi c и Private и проверять зарегистрирован пользователь или нет. Он должен выполнить вызов API, чтобы проверить, есть ли у пользователя действующий сеанс или нет.

Будет полезно, если кто-нибудь сможет исправить мой код или посоветовать, как это исправить, поскольку я изучаю React. Заранее большое спасибо.

Ниже мои коды: Router. js

import React, {Suspense, lazy, useEffect, useState  } from "react"
import { Router, Switch, Route, Redirect } from "react-router-dom"
import { history } from "./history"
import { connect } from "react-redux"
import Spinner from "./components/@project/spinner/Loading-spinner"
import { ContextLayout } from "./utility/context/Layout"
import verifyToken from './authServices/verifyToken'


// Route-based code splitting
const dashboard = lazy(() => import("./views/Dashboards/Dashboard"))
const profile = lazy(() => import("./views/Profile"))

//error Pages
const error404 = lazy(() => import("./views/Misc/error/404"))
const error500 = lazy(() => import("./views/Misc/error/500"))
const authorized = lazy(() => import("./views/Misc/NotAuthorized"))
const maintenance = lazy(() => import("./views/Misc/Maintenance"))
//AuthorizedPages
const Login = lazy(() => import("./views/authentication/login/Login"))
const forgotPassword = lazy(() => import("./views/authentication/ForgotPassword"))
const lockScreen = lazy(() => import("./views/authentication/LockScreen"))
const register = lazy(() => import("./views/authentication/register/Register"))

// Set Layout and Component Using App Route

function useVerified(auth, path){
  const [verified, setVerifiedValue] = useState();
  useEffect(() => {
    const doVerify = async () => {
      setVerifiedValue(await verifyToken(auth))
    }
    doVerify()
  }, [path])
  return verified;
}

const RouteConfig =  ({ component: Component, fullLayout, user, auth, ...rest}) => {
 const path = ({...rest}.path)
 const verified = useVerified(auth, path);
  return <Route
    {...rest} 
    render={props => {
      return (
        <ContextLayout.Consumer>
          {context => {
            let LayoutTag =
              fullLayout === true
                ? context.fullLayout
                : context.VerticalLayout
            
            return  (auth.values !== undefined && auth.values.isSignedIn && verified) ? (
              <LayoutTag {...props} permission={user}>
                <Suspense fallback={<Spinner />}>
                  <Component {...props}></Component>
                </Suspense>
              </LayoutTag>
            ) : (
              <context.fullLayout {...props} permission={user}>
                <Suspense fallback={<Spinner />}>
                  <Login {...props} />
                </Suspense>
              </context.fullLayout>
            )
          }}
        </ContextLayout.Consumer>
      )
    }}
  />
}
const mapStateToProps = state => {
  return {
    user: state.auth.login.userRole,
    auth: state.auth.login
  }
}

const AppRoute = connect(mapStateToProps)(RouteConfig)


const PublicRoute = ({ component: Component, fullLayout, ...rest }) => (
  <Route {...rest} render={() => {
      return (
        <ContextLayout.Consumer>
          {context => {
            let LayoutTag =
              fullLayout === true
                ? context.fullLayout
                : context.VerticalLayout
            return (
              <LayoutTag>
                <Suspense fallback={<Spinner />}>
                  <Component/>
                </Suspense>
              </LayoutTag>
            )
          }}
        </ContextLayout.Consumer>
      )
    }}
  />
)

class AppRouter extends React.Component {
  render() {
    return (
      // Set the directory path if you are deploying in sub-folder
      <Router history={history}>
        <Switch>
          <PublicRoute exact path="/login" component={Login} fullLayout />
          <PublicRoute exact path="/" component={Login} fullLayout />
          <PublicRoute path="/register" component={register} fullLayout />
          <PublicRoute path="/forgot-password"  component={forgotPassword} fullLayout />

          <AppRoute path="/dashboard" component={dashboard} />
          <AppRoute path="/profile" component={profile} />
          
          <AppRoute path="/404" component={error404} fullLayout />
          <AppRoute path="/500" component={error500} fullLayout />
          <AppRoute path="/not-authorized" component={authorized} fullLayout />
          <AppRoute path="/maintenance" component={maintenance} fullLayout />
     
          <AppRoute component={error404} fullLayout />
        </Switch>
      </Router>
    )
  }
}

export default AppRouter

verifyToken. js

import jwt from 'jsonwebtoken';
import { refreshToken } from "../redux/actions/auth/loginActions"

const verifyToken = async props => {
    if('accessToken' in props && 'accessToken' in props.accessToken){
        if (props.accessToken.accessToken !== undefined && props.accessToken.accessToken !== null) {
            if (assertAlive(jwt.decode(props.accessToken.accessToken))) {
                const verified = await refreshToken(props)
                if (verified){
                    return true
                } else {
                    return false
                }
            } else {
                return false
            }
        }else 
            return false
    }else
        return false
}

function assertAlive (decoded) {
    const now = Date.now().valueOf() / 1000
    if (typeof decoded.exp !== 'undefined' && decoded.exp < now) {
      //throw new Error(`token expired: ${JSON.stringify(decoded)}`)
      return false
    }
    if (typeof decoded.nbf !== 'undefined' && decoded.nbf > now) {
      //throw new Error(`token not yet valid: ${JSON.stringify(decoded)}`)
      return false
    }
    return true
  }

export default verifyToken;

Код ВЫЗОВА API

export const  refreshToken =  async  () => {
  const options = { withCredentials: true };
  const resp = await axios.post(process.env.REACT_APP_API_URL+'/api/auth/verifyToken',{}, options).catch(err => {console.log(err); return false;});

  if(resp){
    if (resp.status === 200){
      var loggedInUser, accessToken
      loggedInUser = resp.data.user
      accessToken = resp.data.token
     await store.dispatch({
        type: "LOGIN_WITH_JWT",
        payload: { loggedInUser, loggedInWith: "jwt", isSignedIn: "true", accessToken }
      })
     await store.dispatch({
        type: "ACCESS_TOKEN",
        accessToken: {accessToken }
      })
      return true
    }else if (resp.status === 401){
      return false
    }else{
      return false
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...