react-router-dom 6.8.0自定义PrivateRoute报错,如何正确使用?
自定义PrivateRoute的正确实现与使用
我正在为聊天应用构建自定义PrivateRoute,以下是我的PrivateRoute代码及使用方式,但构建项目时出现错误,请问该如何正确使用自定义PrivateRoute?
原代码示例
import { useState, useEffect } from 'react'; import { Route, Navigate } from 'react-router-dom'; import axios from 'axios'; interface PrivateRouteProps { element: React.ComponentType<any>; path: string; } export function PrivateRoute({ element: Element, path }: PrivateRouteProps) { const [authenticated, setAuthenticated] = useState(false); useEffect(() => { axios .get('http://golang:8080') .then((response) => { if (response.status === 200) { setAuthenticated(true); } }) .catch((error) => { console.log(error); }); }, []); return ( <Route path={path} element={ authenticated ? <Element /> : <Navigate to="/login" replace={true} /> } /> ); }
原使用方式
<PrivateRoute path={RouterPath.ROOT} element={Main} />
问题分析
- React Router v6 API适配问题:v6版本不再支持自定义
Route组件,Routes仅识别官方Route组件,自定义PrivateRoute作为Route的用法会被忽略。 - 初始状态逻辑缺陷:
authenticated初始值为false,鉴权请求未完成时就会强制跳转到登录页,导致用户体验差。 - 类型定义错误:
element属性定义为ComponentType<any>,但实际使用时传入的是组件实例(如<Main />),类型不匹配。
修正后的PrivateRoute实现
import { useState, useEffect } from 'react'; import { Navigate, useLocation } from 'react-router-dom'; import axios from 'axios'; interface PrivateRouteProps { children: React.ReactElement; } export function PrivateRoute({ children }: PrivateRouteProps) { // 初始为null表示鉴权请求未完成 const [authenticated, setAuthenticated] = useState<boolean | null>(null); const location = useLocation(); useEffect(() => { const checkAuthentication = async () => { try { const response = await axios.get('http://golang:8080'); setAuthenticated(response.status === 200); } catch (error) { console.error('鉴权失败:', error); setAuthenticated(false); } }; checkAuthentication(); }, []); // 鉴权中显示加载状态 if (authenticated === null) { return <div>加载中...</div>; // 替换为你的自定义加载UI } // 鉴权通过则渲染子组件,否则跳转到登录页并保存当前路径 return authenticated ? ( children ) : ( <Navigate to="/login" replace state={{ from: location }} /> ); }
正确使用方式
在路由配置中,用PrivateRoute包裹需要保护的组件:
import { Routes, Route } from 'react-router-dom'; import { PrivateRoute } from './PrivateRoute'; import Main from './Main'; import Login from './Login'; function AppRoutes() { return ( <Routes> <Route path="/login" element={<Login />} /> <Route path={RouterPath.ROOT} element={ <PrivateRoute> <Main /> </PrivateRoute> } /> </Routes> ); }
关键改进点
- 采用组件包裹的方式适配React Router v6的API,符合官方推荐的路由保护方案。
- 增加加载状态,避免鉴权请求未完成时的错误跳转。
- 使用
useLocation保存当前路径,登录完成后可跳回原页面(在Login组件中可通过useLocation().state?.from获取)。 - 修正类型定义,使用
children接收组件实例,匹配实际使用场景。
内容的提问来源于stack exchange,提问作者user21022882
相关产品推荐
相关产品推荐

