登录时每次刷新页面都会让我回到仪表板(使用受保护的路由持续登录)

Every page refresh while logged-in brought me back to dashboard (persistent login with protected route)

我已经从 Login 和其他 protected components.

实现了一个简单的 protected route

Login.js

的受保护路线
import React, { useEffect } from 'react'
import { Redirect, Route } from 'react-router-dom'
import { useAuth } from '../../../contexts/Auth/AuthState'
import { isAuthenticated, setLoading } from '../../../contexts/Auth/AuthAction'

const ProtectedRoute\Login = ({ component: Component, ...rest }) => {
  const [authState, authDispatch] = useAuth()
  const { authenticated, loading } = authState

  // check if user is authenticated
  useEffect(() => {
    (async() => {
      await isAuthenticated(authDispatch)
      setLoading(authDispatch, false)
    })();
  }, [])

  return (
    <Route
      {...rest} render={
        props => {
          if(loading) return <div className="lds-hourglass"></div>
          if(!authenticated) return <Component {...props} />
          else return <Redirect exact to={{
            // here I redirect logged-in user to dashboard
            pathname: "/dashboard",
            state: { from: props.location }
          }} />
        }
      } 
    />
  )
}

export default ProtectedRouteLogin

Dashboard.js 或其他受保护组件的受保护路线

import React, { useEffect } from 'react'
import { Redirect, Route } from 'react-router-dom'
import { useAuth } from '../../../contexts/Auth/AuthState'
import { isAuthenticated, setLoading } from '../../../contexts/Auth/AuthAction'

const ProtectedRouteOthers = ({ component: Component, ...rest }) => {
  const [authState, authDispatch] = useAuth()
  const { authenticated, loading } = authState

  // check if user is authenticated
  useEffect(() => {
    (async() => {
      await isAuthenticated(authDispatch)
      setLoading(authDispatch, false)
    })();
  }, [])

  return (
    <Route 
      {...rest} render={
        props => {
          if(loading) return <div className="lds-hourglass"></div>
          if(authenticated) return <Component {...props} />
          else return <Redirect to={
            {
              // here redirect NOT logged-in user back to login page
              pathname: "/login",
              state: { from: props.location }
            }
          } />
        }
      } 
    />
  )
}

export default ProtectedRouteOthers

面临的问题

export const isAuthenticated = async(dispatch) => {
  setLoading(dispatch, true)

  // get user cookie
  let userExist = getCookie('user')

  /** Cookie Checking Style */
  if(userExist) {
    dispatch({
      type: 'SET_ISAUTHENTICATED',
      payload: true
    })
  } else {
    dispatch({
      type: 'SET_ISAUTHENTICATED',
      payload: false
    })
  }
}

那么我如何更改我的代码,以便每次 刷新 我的 protected 页面(登录时-in).我将留在刷新的页面,而不是返回Dashboard页面?

幸运的是我找到了解决方案。但我不知道这是否是一个可以接受的解决方案。至少这个逻辑是有意义的来解决我的问题。

我决定在呈现 Login.js 页面和其他 protected components 之前 添加逻辑 Protected Route components(在ProtectedRouteLogin.js & ProtectedRouteOthers中添加的逻辑)

ProtectedRouteLogin.js

中添加了逻辑
  • 在呈现到 Dashboard.js 页面之前,如果 用户已通过身份验证 ,我会检查 props.location.pathname 已保存 cookie 第一个 中。如果present/exist,那么render就表示pathname。否则,只需 renderDashboard.js
  • ProtectedRouteLogin.js:-
import React, { useEffect } from 'react'
import { Redirect, Route } from 'react-router-dom'
import { useAuth } from '../../../contexts/Auth/AuthState'
import { isAuthenticated, setLoading } from '../../../contexts/Auth/AuthAction'
import { getCookie } from '../../../services/Cookie'

const ProtectedRouteLogin = ({ component: Component, ...rest }) => {
  const [authState, authDispatch] = useAuth()
  const { authenticated, loading } = authState

  // check if user is authenticated
  useEffect(() => {
    (async() => {
      await isAuthenticated(authDispatch)
      setLoading(authDispatch, false)
    })();
  }, [])

  return (
    <Route
      {...rest} render={
        props => {
          if(loading) return <div className="lds-hourglass"></div>
          if(!authenticated) return <Component {...props} />
          else {
            // get pathname save in cookie
            let url = getCookie('onRefresh')
            
            return <Redirect exact to={{
              // ternary function to determine redirection
              pathname: url !== '' ? url : '/pfv4-admin/dashboard',
              state: { from: props.location }
            }} />
          }
        }
      } 
    />
  )
}

export default ProtectedRouteLogin

ProtectedRouteOthers.js

中添加了逻辑
  • 这里,在渲染到 any protected components 之前,我 set cookie 持有即将访问componentprops.location.pathnameurl。这样,我就可以 交叉检查 这个 url 在上面 ProtectedRouteLogin.js
  • ProtectedRouteOthers.js:-
import React, { useEffect } from 'react'
import { Redirect, Route } from 'react-router-dom'
import { useAuth } from '../../../contexts/Auth/AuthState'
import { isAuthenticated, setLoading } from '../../../contexts/Auth/AuthAction'
import { setCookie } from '../../../services/Cookie'

const ProtectedRouteOthers = ({ component: Component, ...rest }) => {
  const [authState, authDispatch] = useAuth()
  const { authenticated, loading } = authState

  // check if user is authenticated
  useEffect(() => {
    (async() => {
      await isAuthenticated(authDispatch)
      setLoading(authDispatch, false)
    })();
  }, [])

  return (
    <Route 
      {...rest} render={
        props => {
          if(loading) return <div className="lds-hourglass"></div>
          if(authenticated) {
            // save last page seen address (url)
            setCookie('onRefresh', props.location.pathname, { path: '/' }) 
            return <Component {...props} />
          }
          else return <Redirect to={
            {
              pathname: "/pfv4-admin",
              state: { from: props.location }
            }
          } />
        }
      } 
    />
  )
}

export default ProtectedRouteOthers

请随时为这个问题添加您自己的可能解决方案。期待尝试。