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;

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

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

示例代码:

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 方法进行重定向。

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 文件(位置可根据自己的习惯存放)
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中引入并设置
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();

你可能感兴趣的:(react,react.js,javascript,前端)