• React Router 路由守卫


    React Router 路由守卫

    组件内路由守卫

    1、下面是使用高阶组件实现路由守卫的示例代码:

    import React from 'react';
    import { Route, Redirect } from 'react-router-dom';
    
    const PrivateRoute = ({ component: Component, isAuthenticated, ...rest }) => (
      <Route
        {...rest}
        render={(props) =>
          isAuthenticated ? (
            <Component {...props} />
          ) : (
            <Redirect to={{ pathname: '/login', state: { from: props.location } }} />
          )
        }
      />
    );
    
    export default PrivateRoute;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在上面的代码中,PrivateRoute 是一个高阶组件,它接收一个组件作为参数,并返回一个新的组件。在 render 方法中,如果用户已经登录,则渲染传入的组件;否则,重定向到登录页面。通过使用该高阶组件,我们可以在需要进行权限验证的路由上使用 PrivateRoute 来保护路由,例如:

    <Switch>
      <PrivateRoute exact path="/" component={Home} isAuthenticated={isAuthenticated} />
      <PrivateRoute path="/dashboard" component={Dashboard} isAuthenticated={isAuthenticated} />
      <Route path="/login" component={Login} />
    </Switch>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    其中 isAuthenticated 是一个布尔值,表示当前用户是否已经登录。

    2、使用 函数组件或 render 属性来实现路由守卫

    React Router 可以使用 Route 组件的 render 属性或函数式组件来实现路由守卫。

    使用 render 属性时,可以传入一个函数,根据需要来渲染不同的组件或页面。在这个函数中可以实现路由守卫的逻辑,例如检查用户是否登录,根据用户角色判断是否有权限访问该页面等。如果不满足条件,可以返回一个重定向或提示信息,否则可以渲染目标组件或页面。

    示例代码

    import { Route, Redirect } from 'react-router-dom';
    
    function PrivateRoute({ component: Component, isAuth, ...rest }) {
      return (
        <Route
          {...rest}
          render={(props) =>
            isAuth ? (
              <Component {...props} />
            ) : (
              <Redirect
                to={{
                  pathname: '/login',
                  state: { from: props.location },
                }}
              />
            )
          }
        />
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在上面的示例中,PrivateRoute 组件接受三个参数:component,代表需要渲染的目标组件;isAuth,代表用户是否已登录;rest,代表其他参数,例如路由路径等。在 render 函数中,如果用户已登录,就渲染目标组件,否则返回一个重定向到登录页面。

    使用函数式组件时,可以将需要实现路由守卫的逻辑直接写在函数组件中,例如在 useEffect 钩子函数中进行判断。如果不满足条件,可以使用 history.push 方法进行重定向。

    import { useEffect } from 'react';
    import { useHistory } from 'react-router-dom';
    
    function PrivatePage() {
      const history = useHistory();
      const isAuth = true;
    
      useEffect(() => {
        if (!isAuth) {
          history.push('/login');
        }
      }, [isAuth, history]);
    
      return <div>Private Page</div>;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在上面的示例中,如果用户未登录,就会使用 history.push 方法将页面重定向到登录页面。这里的 useEffect 钩子函数会在组件渲染完成后执行,也可以根据需要添加其他依赖项。

    全局路由守卫

    虽然React没有路由守卫,但是我们可以通过高阶组件实现相关功能,使用方法如下

    1. 创建 AuthRoute.tsx 文件(位置可根据自己的习惯存放)
    import React from 'react';
    import { Navigate, useLocation } from 'react-router-dom';
    const allowList = ['/login', '/register'];
    const loginRoute = '/login';
    const indexRoute = '/'
    export default function AuthRoute(props) {
      const location = useLocation();
      // children 为子组件
      const { children } = props;
      // 根据 token 对路由进行权限校验,需要和后端配合使用
      // 这里的 token 一般是登陆成功之后拿到后端返回的 token 并通过 Cookie.set('token', token字符串, {
      //    expires: time_limit // 设置存放时间
      // })设置
      let token = false;
      if (token && token !== 'undefined') {
        // 有 token 的状态下禁止用户回到登录页,重定向到首页
        if (location.pathname === loginRoute) {
          return <Navigate to={indexRoute}></Navigate>;
        } else {
          // 其他路由均可正常跳转
          return <>{children}</>;
        }
      } else {
        // 无 token 的状态下,如果要跳转的路由是白名单中的路由,正常跳转
        if (allowList.includes(location.pathname || '')) {
          return <>{children}</>;
        } else {
          // 无 token 且非白名单路由,重定向至登录页
          return <Navigate to={loginRoute}></Navigate>;
        }
      }
    }
    
    //https://zhuanlan.zhihu.com/p/628935247 React Router 组件路由守卫(Route Guard)的机制
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    1. 在 App.tsx中引入并设置
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './styles/basic.scss';
    import App from './App';
    import reportWebVitals from './reportWebVitals';
    import { BrowserRouter } from 'react-router-dom';
    import ThemeContext from './store/themeContext';
    import store from './store';
    import AuthRoute from './auth/auth';
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <BrowserRouter>
          <ThemeContext.Provider
            value={{
              store
            }}
          >
            <AuthRoute>
              <App />
            </AuthRoute>
          </ThemeContext.Provider>
        </BrowserRouter>
      </React.StrictMode>
    );
    
    // If you want to start measuring performance in your app, pass a function
    // to log results (for example: reportWebVitals(console.log))
    // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
    reportWebVitals();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 相关阅读:
    卷积神经网络(CNN)实现服装图像分类
    电脑重装系统后当前安全设置不允许下载该文件
    管理团队按这个模板做,让你成为优秀管理者
    Java 21 虚拟线程:使用指南(一)
    Gbase数据库
    使用venv创建python虚拟环境
    jenkins部署
    神经网络 02(激活函数)
    大二学生基于Html+Css+javascript的网页制作——动漫设计公司响应式网站模板 (10个页面)
    【MySQL数据库原理】MySQL Community 8.0界面工具汉化
  • 原文地址:https://blog.csdn.net/song854601134/article/details/132764870