React Router

10月 1, 2025
Frontend, React, ByAI

React Router 是一个适用于 React 的多策略路由器,这里详细介绍如何在 React 项目中使用 React Router。

🔧 安装与基础设置#

1. 安装 React Router#

# 使用 npm
npm install react-router-dom

# 使用 yarn
yarn add react-router-dom

# 使用 bun
bun add react-router-dom

2. 基础路由设置#

// main.jsx 或 index.js
import React from 'react'
import ReactDOM from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import App from './App'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
)

🎯 核心组件与 Hook#

1. 基本路由配置#

// App.jsx
import { Routes, Route } from 'react-router-dom'
import Home from './pages/Home'
import About from './pages/About'
import Contact from './pages/Contact'
import Navbar from './components/Navbar'

function App() {
  return (
    <div className="app">
      <Navbar />
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
      </Routes>
    </div>
  )
}

export default App

2. 导航组件#

// components/Navbar.jsx
import { Link, NavLink } from 'react-router-dom'

function Navbar() {
  return (
    <nav>
      {/* Link - 普通导航链接 */}
      <Link to="/">首页</Link>
      
      {/* NavLink - 支持激活状态的链接 */}
      <NavLink 
        to="/about"
        className={({ isActive }) => isActive ? 'active' : ''}
      >
        关于我们
      </NavLink>
      
      <NavLink to="/contact">
        {({ isActive }) => (
          <span className={isActive ? 'text-blue-500' : ''}>
            联系我们
          </span>
        )}
      </NavLink>
    </nav>
  )
}

🔄 动态路由与参数#

1. 动态路由参数#

// App.jsx - 路由配置
<Routes>
  <Route path="/users" element={<UserList />} />
  <Route path="/users/:userId" element={<UserProfile />} />
  <Route path="/products/:category/:id" element={<ProductDetail />} />
</Routes>

2. 获取路由参数#

// pages/UserProfile.jsx
import { useParams, useSearchParams } from 'react-router-dom'

function UserProfile() {
  // 获取路径参数
  const { userId } = useParams()
  
  // 获取查询参数
  const [searchParams, setSearchParams] = useSearchParams()
  const tab = searchParams.get('tab')
  const sort = searchParams.get('sort')

  const updateQueryParams = () => {
    setSearchParams({ tab: 'info', sort: 'asc' })
  }

  return (
    <div>
      <h1>用户资料: {userId}</h1>
      <p>当前标签: {tab}</p>
      <button onClick={updateQueryParams}>更新查询参数</button>
    </div>
  )
}

🎪 编程式导航#

// components/LoginForm.jsx
import { useNavigate, useLocation } from 'react-router-dom'

function LoginForm() {
  const navigate = useNavigate()
  const location = useLocation()

  const handleLogin = async () => {
    try {
      // 模拟登录逻辑
      await loginUser()
      
      // 登录后跳转
      const from = location.state?.from?.pathname || '/dashboard'
      navigate(from, { replace: true })
      
      // 其他导航方式
      // navigate(-1) // 返回上一页
      // navigate('/dashboard', { state: { user: userData } }) // 传递状态
    } catch (error) {
      console.error('登录失败')
    }
  }

  return (
    <form onSubmit={(e) => {
      e.preventDefault()
      handleLogin()
    }}>
      {/* 表单内容 */}
      <button type="submit">登录</button>
    </form>
  )
}

🏗️ 嵌套路由#

1. 定义嵌套路由#

// App.jsx
<Routes>
  <Route path="/dashboard" element={<DashboardLayout />}>
    <Route index element={<DashboardHome />} />
    <Route path="profile" element={<Profile />} />
    <Route path="settings" element={<Settings />} />
    <Route path="analytics" element={<Analytics />} />
  </Route>
</Routes>

2. 布局组件中使用 Outlet#

// layouts/DashboardLayout.jsx
import { Outlet, Link } from 'react-router-dom'

function DashboardLayout() {
  return (
    <div className="dashboard-layout">
      <aside className="sidebar">
        <nav>
          <Link to="/dashboard">概览</Link>
          <Link to="/dashboard/profile">个人资料</Link>
          <Link to="/dashboard/settings">设置</Link>
          <Link to="/dashboard/analytics">分析</Link>
        </nav>
      </aside>
      
      <main className="main-content">
        {/* 子路由将在这里渲染 */}
        <Outlet />
      </main>
    </div>
  )
}

🛡️ 保护路由与权限控制#

1. 路由保护组件#

// components/ProtectedRoute.jsx
import { Navigate, useLocation } from 'react-router-dom'

function ProtectedRoute({ children, requiredRole }) {
  const location = useLocation()
  const { user, isAuthenticated } = useAuth() // 假设有认证 Hook

  if (!isAuthenticated) {
    // 重定向到登录页,并保存当前位置以便登录后返回
    return <Navigate to="/login" state={{ from: location }} replace />
  }

  if (requiredRole && user.role !== requiredRole) {
    // 权限不足
    return <Navigate to="/unauthorized" replace />
  }

  return children
}

2. 使用保护路由#

// App.jsx
<Routes>
  <Route path="/admin" element={
    <ProtectedRoute requiredRole="admin">
      <AdminLayout />
    </ProtectedRoute>
  }>
    <Route index element={<AdminDashboard />} />
    <Route path="users" element={<UserManagement />} />
  </Route>
  
  <Route path="/profile" element={
    <ProtectedRoute>
      <UserProfile />
    </ProtectedRoute>
  } />
</Routes>

📚 高级功能#

1. 懒加载路由#

import { lazy, Suspense } from 'react'

const LazyDashboard = lazy(() => import('./pages/Dashboard'))
const LazyAdmin = lazy(() => import('./pages/Admin'))

function App() {
  return (
    <Routes>
      <Route 
        path="/dashboard" 
        element={
          <Suspense fallback={<div>加载中...</div>}>
            <LazyDashboard />
          </Suspense>
        } 
      />
    </Routes>
  )
}

2. 404 页面处理#

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/about" element={<About />} />
  <Route path="*" element={<NotFound />} />
</Routes>

3. 路由配置对象(v6.4+ 数据路由)#

import { createBrowserRouter, RouterProvider } from 'react-router-dom'

const router = createBrowserRouter([
  {
    path: '/',
    element: <RootLayout />,
    children: [
      { index: true, element: <Home /> },
      { 
        path: 'users',
        element: <Users />,
        loader: usersLoader, // 数据加载器
        action: userAction   // 数据操作
      }
    ]
  }
])

// 在 main.jsx 中使用
ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <RouterProvider router={router} />
  </React.StrictMode>
)

💡 最佳实践#

  1. 文件组织
src/
  components/
  pages/
    Home.jsx
    About.jsx
    users/
      UserList.jsx
      UserProfile.jsx
  layouts/
    MainLayout.jsx
    DashboardLayout.jsx
  routes/
    index.jsx
  1. 路由集中管理
// routes/index.jsx
import { useRoutes } from 'react-router-dom'
import routesConfig from './routesConfig'

function Router() {
  return useRoutes(routesConfig)
}

export default Router
  1. 类型安全(使用 TypeScript):
// types/router.d.ts
declare module 'react-router-dom' {
  interface ParamKeys {
    userId: string
    productId: string
  }
}

React Router 提供了强大而灵活的路由解决方案,从简单的 SPA 导航到复杂的企业级应用路由管理都能胜任。掌握这些核心概念后,你可以根据项目需求选择合适的路由模式和组织方式。