v6路由权限控制实现踩坑:路由守卫最佳实践

FreeYvonne +0/-0 0 0 正常 2025-12-24T07:01:19 React Router

React Router v6 路由权限控制实现踩坑

React Router v6 相比 v5 在路由守卫的实现上有了较大变化,特别是 useNavigateuseLocation 的使用方式。本文将分享在升级过程中遇到的常见问题和最佳实践。

核心问题

在 v6 中,<Route> 组件不再支持 component 属性,而是通过 element 属性来渲染组件。这导致传统的路由守卫实现方式需要调整。

解决方案

1. 基础权限守卫组件

const ProtectedRoute = ({ children }) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const navigate = useNavigate();

  useEffect(() => {
    // 检查用户认证状态
    const checkAuth = async () => {
      try {
        const token = localStorage.getItem('token');
        if (!token) {
          navigate('/login');
          return;
        }
        
        // 验证 token
        const response = await verifyToken(token);
        setIsAuthenticated(response.isValid);
        
        if (!response.isValid) {
          navigate('/login');
        }
      } catch (error) {
        navigate('/login');
      }
    };

    checkAuth();
  }, [navigate]);

  return isAuthenticated ? children : <div>加载中...</div>;
};

2. 路由配置中的使用

<Routes>
  <Route path="/login" element={<Login />} />
  <Route 
    path="/dashboard" 
    element={
      <ProtectedRoute>
        <Dashboard />
      </ProtectedRoute>
    }
  />
</Routes>

3. 优化方案 - 自定义 Hook

const useAuth = () => {
  const [authState, setAuthState] = useState({
    isAuthenticated: false,
    loading: true,
    user: null
  });

  useEffect(() => {
    const verifyUser = async () => {
      const token = localStorage.getItem('token');
      if (!token) {
        setAuthState({
          isAuthenticated: false,
          loading: false,
          user: null
        });
        return;
      }

      try {
        const userData = await validateToken(token);
        setAuthState({
          isAuthenticated: true,
          loading: false,
          user: userData
        });
      } catch (error) {
        localStorage.removeItem('token');
        setAuthState({
          isAuthenticated: false,
          loading: false,
          user: null
        });
      }
    };

    verifyUser();
  }, []);

  return authState;
};

常见踩坑点

  1. useNavigate 必须在路由组件内使用
  2. 权限检查逻辑需要考虑异步加载
  3. 重新认证后需要刷新页面状态
  4. 路由跳转时的错误处理

通过以上方案,可以有效实现 v6 版本的路由权限控制,避免常见的认证问题。

推广
广告位招租

讨论

0/2000
梦想实践者
梦想实践者 · 2026-01-08T10:24:58
v6路由守卫确实比v5复杂不少,核心是理解element属性替代component后,如何在组件层级做权限判断。
灵魂画家
灵魂画家 · 2026-01-08T10:24:58
别把权限检查逻辑写死在ProtectedRoute里,应该抽成自定义hook,比如useAuthStatus,复用性更好。
Julia953
Julia953 · 2026-01-08T10:24:58
加载中状态建议用Skeleton或Spinner组件,别直接返回文字,用户体验差,特别是移动端。
Frank20
Frank20 · 2026-01-08T10:24:58
token验证建议加上防抖处理,避免频繁请求接口导致性能问题,可以结合useMemo缓存结果。
Gerald249
Gerald249 · 2026-01-08T10:24:58
如果项目有多个权限级别,建议在ProtectedRoute里增加role字段校验,而不仅是登录状态。
网络安全侦探
网络安全侦探 · 2026-01-08T10:24:58
路由守卫最好配合context使用,把用户信息和权限状态统一管理,而不是每个组件都去localStorage取。
SoftSeed
SoftSeed · 2026-01-08T10:24:58
别忘了处理403无权限访问的情况,可以在ProtectedRoute中增加权限判断逻辑,跳转到对应页面。
WellVictor
WellVictor · 2026-01-08T10:24:58
建议用React.lazy + Suspense做权限路由的懒加载,避免首屏加载过多组件影响性能。