React TS实现路由守卫报错:GuardedRoute不是Route组件
解决方案:React Router v6 路由守卫报错处理
错误原因
React Router v6 对 <Routes> 的直接子节点有严格限制,必须是 <Route> 或 <React.Fragment> 组件。你自定义的 <GuardedRoute> 不属于这两类组件,直接作为 <Routes> 的子元素会触发该错误。
方案一:守卫组件包裹路由元素
修改 GuardedRoute.tsx,让它成为一个权限判断的包装组件,接收需要守卫的组件作为子元素,根据用户状态返回目标组件或跳转:
import { Navigate } from 'react-router-dom'; import { useUserInfo } from '../context/UserContext'; import type { ReactNode } from 'react'; export const GuardedRoute = ({ children }: { children: ReactNode }) => { const { userInfo } = useUserInfo(); // 验证用户登录状态,已登录则渲染目标组件,否则跳转到首页 return userInfo.id !== '' ? children : <Navigate to="/" replace />; };
在 App.tsx 中,用 GuardedRoute 包裹需要权限验证的路由元素:
<BrowserRouter> <Nav></Nav> <div className="w-[100vw] fixed top-[50px] z-[100] flex flex-col"> {ErrorMessages.map((message, index) => ( <div className="w-[300px] h-[50px] mt-[10px] mx-auto bg-red-600/90 rounded-md grid place-content-center" key={index}> <p className="font-bold text-gray-200 text-center">{message}</p> </div> ))} </div> <Routes> <Route path="/" element={<Home />} /> {/* 用GuardedRoute守卫需要权限的页面 */} <Route path="/profile/:select?" element={<GuardedRoute><Profile /></GuardedRoute>} /> <Route path="/checkout" element={<GuardedRoute><CheckOut /></GuardedRoute>}/> <Route path="/register" element={<Register />} /> <Route path="/login" element={<Login />} /> <Route path="/browse" element={<Browse />} /> <Route path="/product/:id" element={<Product />} /> <Route path="/404" element={<PageNotFound />}/> <Route path="*" element={<Navigate to="/404" />}/> </Routes> </BrowserRouter>
方案二:嵌套路由统一守卫(更整洁)
如果有多个需要权限验证的路由,可以用嵌套路由的方式,将守卫逻辑作为父路由的元素,统一管理:
修改 GuardedRoute.tsx,使用 <Outlet> 渲染子路由内容:
import { Navigate, Outlet } from 'react-router-dom'; import { useUserInfo } from '../context/UserContext'; export const GuardedRoute = () => { const { userInfo } = useUserInfo(); // 用户未登录则跳转首页 if (userInfo.id === '') { return <Navigate to="/" replace />; } // Outlet会自动渲染匹配的子路由组件 return <Outlet />; };
在 App.tsx 中,将需要守卫的路由作为 GuardedRoute 的子路由:
<BrowserRouter> <Nav></Nav> <div className="w-[100vw] fixed top-[50px] z-[100] flex flex-col"> {ErrorMessages.map((message, index) => ( <div className="w-[300px] h-[50px] mt-[10px] mx-auto bg-red-600/90 rounded-md grid place-content-center" key={index}> <p className="font-bold text-gray-200 text-center">{message}</p> </div> ))} </div> <Routes> <Route path="/" element={<Home />} /> {/* 父路由统一处理权限验证,子路由为需要守卫的页面 */} <Route element={<GuardedRoute />}> <Route path="/profile/:select?" element={<Profile />} /> <Route path="/checkout" element={<CheckOut />}/> </Route> <Route path="/register" element={<Register />} /> <Route path="/login" element={<Login />} /> <Route path="/browse" element={<Browse />} /> <Route path="/product/:id" element={<Product />} /> <Route path="/404" element={<PageNotFound />}/> <Route path="*" element={<Navigate to="/404" />}/> </Routes> </BrowserRouter>
内容的提问来源于stack exchange,提问作者Mat
相关产品推荐
相关产品推荐

