React Router 路由守卫

React Router 路由守卫

组件内路由守卫

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

js 复制代码
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;

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

js 复制代码
<Switch>
  <PrivateRoute exact path="/" component={Home} isAuthenticated={isAuthenticated} />
  <PrivateRoute path="/dashboard" component={Dashboard} isAuthenticated={isAuthenticated} />
  <Route path="/login" component={Login} />
</Switch>

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

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

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

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

示例代码:

js 复制代码
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 },
            }}
          />
        )
      }
    />
  );
}

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

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

js 复制代码
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>;
}

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

全局路由守卫

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

  1. 创建 AuthRoute.tsx 文件(位置可根据自己的习惯存放)
js 复制代码
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. 在 App.tsx中引入并设置
js 复制代码
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();
相关推荐
xkxnq6 分钟前
第八阶段:工程化、质量管控与高级拓展(130天),Vue端到端测试:Cypress自动化测试(登录流程+表单提交+页面跳转)
前端·vue.js·flutter
小雨下雨的雨8 分钟前
基于鸿蒙PC Electron框架技术完成的五子棋游戏 - 技术实现详解
前端·javascript·游戏·华为·electron·鸿蒙
cheems95279 分钟前
[开发日记]Spring Boot + MyBatis-Plus 抽奖系统开发复盘:从奖品创建、活动校验到前端圈选人员失效的一次完整排障
前端·spring boot·mybatis
老毛肚10 分钟前
jeecgboot vue API 拆分02
前端·javascript·vue.js
赵谨言16 分钟前
基于C#的在线编码与自动化测试全栈Web平台的设计与实现
开发语言·前端·c#
Raink老师20 分钟前
【AI面试临阵磨枪-98】前端如何展示多模态流式输出:文字打字机 + 图片渐进 + 音频播放?
前端·人工智能·面试
AI_零食24 分钟前
奶茶大数据运维表 - 鸿蒙PC Electron框架技术实现详解
运维·前端·华为·electron·开源·harmonyos·鸿蒙
小雨下雨的雨25 分钟前
鸿蒙PC Electron框架实现流体气泡模拟器
前端·人工智能·算法·华为·electron·鸿蒙
ZC跨境爬虫26 分钟前
跟着 MDN 学JavaScript day_4:如何存储你需要的信息——变量
开发语言·前端·javascript·ui·ecmascript
星栈独行28 分钟前
10 分钟跑起第一个 Makepad 应用:先把窗口开起来
前端·程序人生·ui·rust·开源·github