React Router v6 路由权限控制实现踩坑
React Router v6 相比 v5 在路由守卫的实现上有了较大变化,特别是 useNavigate 和 useLocation 的使用方式。本文将分享在升级过程中遇到的常见问题和最佳实践。
核心问题
在 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;
};
常见踩坑点
useNavigate必须在路由组件内使用- 权限检查逻辑需要考虑异步加载
- 重新认证后需要刷新页面状态
- 路由跳转时的错误处理
通过以上方案,可以有效实现 v6 版本的路由权限控制,避免常见的认证问题。

讨论