React Router V6如何在同路径'/'按登录状态渲染不同组件?
在React Router V6中通过Outlet实现Login与Dashboard共用根路径'/'
需求说明
希望根路径/在用户已登录时渲染Dashboard组件,未登录时渲染Login组件,且通过PublicOutlet和PrivateOutlet这类权限控制组件实现,而非直接在路由的element中写判断逻辑。
现有代码问题
原代码中PublicOutlet和PrivateOutlet的逻辑是跳转路由(已登录访问公共路由跳转到/dashboard,未登录访问私有路由跳转到/login),无法实现同一路径下渲染不同组件的需求。
优化解决方案
调整路由结构和Outlet组件逻辑,让根路径动态匹配不同权限的Outlet,同时保留原有权限控制能力:
import { lazy, Suspense, useMemo } from 'react' import { Route, BrowserRouter, Routes, Navigate, Outlet, } from 'react-router-dom' import * as PATHS from './constants/routes' import UserContext from './context/user' import useAuthListener from './hooks/use-auth-listener' const Login = lazy(() => import('./pages/Login')) const Register = lazy(() => import('./pages/Register')) const NotFound = lazy(() => import('./pages/NotFound')) const Dashboard = lazy(() => import('./pages/Dashboard')) const PrivateOutlet = () => { const { user } = useAuthListener() // 未登录时跳转到根路径(显示Login) return user ? <Outlet /> : <Navigate to="/" replace /> } const PublicOutlet = () => { const { user } = useAuthListener() // 已登录时跳转到根路径(显示Dashboard) return !user ? <Outlet /> : <Navigate to="/" replace /> } const App = () => { const { user } = useAuthListener() const value = useMemo( () => ({ user, }), [user] // 修正依赖项,避免不必要重渲染 ) return ( <UserContext.Provider value={value}> <Suspense fallback={<p>Loading...</p>}> <BrowserRouter> <Routes> {/* 根路径:根据用户状态动态渲染权限Outlet */} <Route path="/" element={user ? <PrivateOutlet /> : <PublicOutlet />}> {/* 已登录时PrivateOutlet渲染Dashboard */} <Route index element={<Dashboard />} /> {/* 未登录时PublicOutlet渲染Login */} <Route index element={<Login />} /> </Route> {/* 公共路由:Register,已登录访问自动跳转到根路径 */} <Route element={<PublicOutlet />}> <Route path={PATHS.SIGNUP} element={<Register />} /> {/* 原Login路由重定向到根路径,统一访问入口 */} <Route path={PATHS.LOGIN} element={<Navigate to="/" replace />} /> </Route> {/* 私有路由:NotFound,未登录访问自动跳转到根路径 */} <Route element={<PrivateOutlet />}> <Route path={PATHS.NOTFOUND} element={<NotFound />} /> {/* 原Dashboard路由重定向到根路径,统一访问入口 */} <Route path={PATHS.DASHBOARD} element={<Navigate to="/" replace />} /> </Route> </Routes> </BrowserRouter> </Suspense> </UserContext.Provider> ) } export default App
方案优势
- 路径统一:无论登录状态如何,用户访问的都是根路径
/,仅渲染组件不同。 - 复用权限组件:保留
PublicOutlet和PrivateOutlet的复用性,其他路由(如Register、NotFound)仍可通过这两个组件实现权限控制。 - 符合路由设计:遵循React Router V6嵌套路由的设计理念,将权限控制逻辑封装在Outlet组件中,避免路由与业务逻辑耦合。
- 优化依赖项:修正
useMemo的依赖项,减少不必要的组件重渲染。
内容的提问来源于stack exchange,提问作者Youssef.K
相关产品推荐
相关产品推荐

