You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

方案优势

  1. 路径统一:无论登录状态如何,用户访问的都是根路径/,仅渲染组件不同。
  2. 复用权限组件:保留PublicOutlet和PrivateOutlet的复用性,其他路由(如Register、NotFound)仍可通过这两个组件实现权限控制。
  3. 符合路由设计:遵循React Router V6嵌套路由的设计理念,将权限控制逻辑封装在Outlet组件中,避免路由与业务逻辑耦合。
  4. 优化依赖项:修正useMemo的依赖项,减少不必要的组件重渲染。

内容的提问来源于stack exchange,提问作者Youssef.K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:24:47