React路由报错:Routes子组件需为Route,如何修复ProtectedRoute重定向?
React Router 受保护路由重定向错误解决方法
问题场景
我有一个React项目,主组件通过路由服务渲染路由,希望实现:主页、404页、登录页对所有用户开放,部分页面仅允许已登录用户访问。为此自定义了ProtectedRoute组件,意图在未登录用户访问受保护页面时重定向到登录页,但运行时出现以下报错:
router.ts:5 Uncaught Error: [ProtectedRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment> at invariant (router.ts:5:1)
现有代码
主组件
const App: React.FC = () => { return <BaseLayout>{RoutingService.getRoutes()}</BaseLayout>; } export default App;
路由服务
class RoutingService { static getRoutes = (): React.ReactNode => { return ( <Routes> <Route key={makeRandomKey()} path={PATHS.ROOT_PATH} element={<MainPage/>}/> <Route key={makeRandomKey()} path={PATHS.AUTH_PATH} element={<LoginPage/>}/> <Route key={makeRandomKey()} path={PATHS.NOT_FOUND_PATH} element={<UnderConstructPage/>}/> <ProtectedRoute path={PATHS.SEARCH_HISTORY_PATH} element={<SearchHistoryPage/>}/> <ProtectedRoute path={PATHS.USER_CABINET_PATH} element={<UserCabinetPage/>}/> </Routes> ); }; } export default RoutingService;
现有ProtectedRoute组件
interface ProtectedRouteProps { path: string; element: React.ReactNode; } const ProtectedRoute: React.FC<ProtectedRouteProps> = ({path, element}) => { const isAuthenticated: boolean = useSelector((state: RootState) => !!state.user.userData?.auth?.token); return isAuthenticated ? <Route path={path} element={element}/> : <> <Navigate to="/auth" replace/></> ; }; export default ProtectedRoute;
错误原因
React Router的<Routes>组件仅接受<Route>或<React.Fragment>作为直接子元素,而当前ProtectedRoute既不是<Route>也不是合法的直接子元素,因此触发报错。
正确实现方式
修改ProtectedRoute组件
将ProtectedRoute改为路由元素的包装器,不再返回<Route>组件:
interface ProtectedRouteProps { children: React.ReactNode; } const ProtectedRoute: React.FC<ProtectedRouteProps> = ({children}) => { const isAuthenticated: boolean = useSelector((state: RootState) => !!state.user.userData?.auth?.token); if (!isAuthenticated) { return <Navigate to="/auth" replace />; } return <>{children}</>; }; export default ProtectedRoute;
更新路由服务
在<Route>的element属性中用ProtectedRoute包裹受保护页面:
class RoutingService { static getRoutes = (): React.ReactNode => { return ( <Routes> <Route key={makeRandomKey()} path={PATHS.ROOT_PATH} element={<MainPage/>}/> <Route key={makeRandomKey()} path={PATHS.AUTH_PATH} element={<LoginPage/>}/> <Route key={makeRandomKey()} path={PATHS.NOT_FOUND_PATH} element={<UnderConstructPage/>}/> <Route key={makeRandomKey()} path={PATHS.SEARCH_HISTORY_PATH} element={<ProtectedRoute><SearchHistoryPage/></ProtectedRoute>} /> <Route key={makeRandomKey()} path={PATHS.USER_CABINET_PATH} element={<ProtectedRoute><UserCabinetPage/></ProtectedRoute>} /> </Routes> ); }; } export default RoutingService;
核心逻辑说明
- 让
ProtectedRoute作为<Route>的element值,完全符合<Routes>对直接子元素的要求。 - 组件内部根据登录状态,决定渲染受保护页面还是执行重定向逻辑,实现权限控制的核心需求。
内容的提问来源于stack exchange,提问作者Sam Fisher
相关产品推荐
相关产品推荐

