Skip to content

React 中,如何实现类似于 Vue-router 提供的路由守卫?

参考答案:

在 React 中,虽然没有像 Vue-router 这样内置的路由守卫功能,但我们可以通过组合 React Router 和一些自定义逻辑来实现类似于 Vue-router 提供的路由守卫功能。

下面介绍几种实现方式。

方法一:使用 useEffect 钩子在组件层面实现

对于需要进行路由守卫的组件,可以在组件的 useEffect 中添加相应的导航逻辑。这种方式类似于 Vue 的 beforeRouteEnter 守卫。

js
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

function ProtectedComponent() {
  const navigate = useNavigate();

  useEffect(() => {
    const isAuthenticated = checkAuthentication(); // 自定义的身份验证逻辑
    if (!isAuthenticated) {
      navigate('/login'); // 如果未登录,重定向到登录页面
    }
  }, [navigate]);

  return <div>Protected Content</div>;
}

方法二:使用高阶组件 (Higher-Order Component)

通过高阶组件(HOC),可以将路由守卫的逻辑封装在组件外部,从而实现类似全局路由守卫的功能。

js
import { useNavigate } from 'react-router-dom';
import React, { useEffect } from 'react';

const withAuthGuard = (WrappedComponent) => {
  return (props) => {
    const navigate = useNavigate();

    useEffect(() => {
      const isAuthenticated = checkAuthentication(); // 自定义的验证逻辑
      if (!isAuthenticated) {
        navigate('/login'); // 如果未通过验证,重定向
      }
    }, [navigate]);

    return <WrappedComponent {...props} />;
  };
};

const ProtectedComponent = () => {
  return <div>Protected Content</div>;
};

export default withAuthGuard(ProtectedComponent);

方法三:通过 React Router Outlet 和中间件模式

React Router 提供了 <Outlet /> 组件,它可以允许我们将路由守卫逻辑应用到某些路由集合上。可以通过中间件模式对路由进行守卫。

js
import { Navigate, Outlet } from 'react-router-dom';

const ProtectedRoute = ({ isAuthenticated }) => {
  return isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
};

// 使用:
<Route path="/protected" element={<ProtectedRoute isAuthenticated={authStatus} />}>
  <Route path="dashboard" element={<Dashboard />} />
  <Route path="settings" element={<Settings />} />
</Route>

在上面的例子中,如果用户未通过身份验证,ProtectedRoute 将重定向到 /login,否则允许继续加载子路由。

方法四:在路由配置中实现路由守卫逻辑

可以通过在路由配置中直接实现身份验证或其他守卫逻辑。

js
import { Route, Routes, Navigate } from 'react-router-dom';

function PrivateRoute({ element: Component, isAuthenticated, ...rest }) {
  return (
    <Route
      {...rest}
      element={isAuthenticated ? <Component /> : <Navigate to="/login" />}
    />
  );
}

function App() {
  const isAuthenticated = checkAuthentication(); // 自定义验证逻辑

  return (
    <Routes>
      <Route path="/login" element={<Login />} />
      <PrivateRoute path="/dashboard" element={<Dashboard />} isAuthenticated={isAuthenticated} />
    </Routes>
  );
}

方法五:使用 Redux 或 Context 实现全局守卫

结合 useContextRedux,可以将身份验证状态存储在全局状态中,然后在每个需要守卫的组件或路由上进行判断。

  1. 通过 Context 实现:
js
import { useContext, useEffect } from 'react';
import { AuthContext } from './AuthProvider';
import { useNavigate } from 'react-router-dom';

function ProtectedComponent() {
  const { isAuthenticated } = useContext(AuthContext);
  const navigate = useNavigate();

  useEffect(() => {
    if (!isAuthenticated) {
      navigate('/login'); // 重定向到登录页面
    }
  }, [isAuthenticated, navigate]);

  return <div>Protected Content</div>;
}
  1. 通过 Redux 实现:
js
import { useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';

function ProtectedComponent() {
  const isAuthenticated = useSelector(state => state.auth.isAuthenticated);
  const navigate = useNavigate();

  useEffect(() => {
    if (!isAuthenticated) {
      navigate('/login');
    }
  }, [isAuthenticated, navigate]);

  return <div>Protected Content</div>;
}

题目要点:

在 React 中实现类似 Vue-router 的路由守卫,常见的方式包括使用 useEffect 钩子、封装高阶组件、利用 React Router 的 <Outlet /> 组件进行中间件式守卫、在路由配置中实现守卫逻辑,或者通过全局状态管理工具(如 Redux 或 Context)进行守卫。