Skip to content

React 路由

React Router 是 React 官方推荐的路由库,它允许我们在 React 应用中实现单页面应用(SPA)的导航功能。本章节将介绍 React Router v6 的基本使用方法。

10.1 什么是路由?

路由的定义

路由是指根据 URL 的变化来展示不同的页面内容。在单页面应用(SPA)中,路由可以实现页面的切换而不需要刷新整个页面。

单页面应用(SPA)原理

  • 传统多页面应用:每次导航都会请求新的 HTML 页面
  • 单页面应用:只加载一个 HTML 页面,通过 JavaScript 动态更新内容
  • 优势:更快的页面切换速度,更好的用户体验

10.2 React Router v6 安装与配置

安装

bash
npm install react-router-dom

基本配置

jsx
// src/App.jsx
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import NotFound from './pages/NotFound';

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

10.3 核心组件使用

BrowserRouter

BrowserRouter 是 React Router 的根组件,它使用 HTML5 的 History API 来管理路由。

jsx
import { BrowserRouter } from 'react-router-dom';

function App() {
  return (
    <BrowserRouter>
      {/* 路由配置 */}
    </BrowserRouter>
  );
}

Routes 和 Route

Routes 是路由容器,Route 定义单个路由规则。

jsx
import { Routes, Route } from 'react-router-dom';

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="/about" element={<About />} />
      <Route path="/users/:id" element={<User />} />
      <Route path="*" element={<NotFound />} />
    </Routes>
  );
}

Link 用于创建导航链接,NavLinkLink 的增强版,支持激活状态。

jsx
import { Link, NavLink } from 'react-router-dom';

function Navigation() {
  return (
    <nav>
      <Link to="/">首页</Link>
      <Link to="/about">关于</Link>
      <NavLink to="/contact" activeClassName="active">
        联系我们
      </NavLink>
    </nav>
  );
}

10.4 路由参数

动态路由参数

jsx
// 路由配置
<Route path="/users/:id" element={<User />} />

// 组件中获取参数
import { useParams } from 'react-router-dom';

function User() {
  const { id } = useParams();
  
  return <h1>用户 ID:{id}</h1>;
}

查询参数

jsx
// 跳转到带查询参数的路由
import { Link, useNavigate } from 'react-router-dom';

function Home() {
  const navigate = useNavigate();
  
  function goToSearch() {
    navigate('/search?keyword=React&page=1');
  }
  
  return (
    <div>
      <Link to="/search?keyword=React&page=1">搜索 React</Link>
      <button onClick={goToSearch}>搜索 React</button>
    </div>
  );
}

// 组件中获取查询参数
import { useSearchParams } from 'react-router-dom';

function Search() {
  const [searchParams, setSearchParams] = useSearchParams();
  const keyword = searchParams.get('keyword');
  const page = searchParams.get('page');
  
  function changePage(newPage) {
    setSearchParams({ keyword, page: newPage });
  }
  
  return (
    <div>
      <p>关键词:{keyword}</p>
      <p>页码:{page}</p>
      <button onClick={() => changePage(2)}>第 2 页</button>
    </div>
  );
}

10.5 嵌套路由

嵌套路由允许我们在父路由中定义子路由,实现页面的嵌套布局。

jsx
// 路由配置
<Route path="/dashboard" element={<Dashboard />}>
  <Route index element={<DashboardHome />} />
  <Route path="profile" element={<Profile />} />
  <Route path="settings" element={<Settings />} />
</Route>

// Dashboard 组件
import { Outlet, Link } from 'react-router-dom';

function Dashboard() {
  return (
    <div>
      <h1>仪表盘</h1>
      <nav>
        <Link to="/dashboard">首页</Link>
        <Link to="/dashboard/profile">个人资料</Link>
        <Link to="/dashboard/settings">设置</Link>
      </nav>
      <Outlet /> {/* 子路由内容将在这里渲染 */}
    </div>
  );
}

10.6 路由重定向

使用 Navigate 组件实现路由重定向。

jsx
import { Navigate } from 'react-router-dom';

// 重定向到首页
<Route path="/old-home" element={<Navigate to="/" replace />} />

// 条件重定向
function ProtectedRoute({ children }) {
  const isLoggedIn = false; // 实际应用中应该从状态管理中获取
  
  if (!isLoggedIn) {
    return <Navigate to="/login" replace />;
  }
  
  return children;
}

// 使用
<Route path="/dashboard" element={<ProtectedRoute><Dashboard /></ProtectedRoute>} />

10.7 404页面配置

使用通配符 * 来匹配未定义的路由,实现 404 页面。

jsx
<Route path="*" element={<NotFound />} />

// NotFound 组件
function NotFound() {
  return (
    <div>
      <h1>404</h1>
      <p>页面未找到</p>
      <Link to="/">返回首页</Link>
    </div>
  );
}

10.8 编程式导航

使用 useNavigate 钩子实现编程式导航。

jsx
import { useNavigate } from 'react-router-dom';

function LoginForm() {
  const navigate = useNavigate();
  
  function handleSubmit() {
    // 登录逻辑
    navigate('/dashboard');
  }
  
  function goBack() {
    navigate(-1); // 后退一步
  }
  
  function goForward() {
    navigate(1); // 前进一步
  }
  
  return (
    <div>
      <form onSubmit={handleSubmit}>
        {/* 表单内容 */}
        <button type="submit">登录</button>
      </form>
      <button onClick={goBack}>返回</button>
      <button onClick={goForward}>前进</button>
    </div>
  );
}

10.9 路由守卫

简单的路由守卫

jsx
import { Navigate, useLocation } from 'react-router-dom';

function RequireAuth({ children }) {
  const isLoggedIn = false; // 实际应用中应该从状态管理中获取
  const location = useLocation();
  
  if (!isLoggedIn) {
    // 保存当前位置,登录后可以重定向回来
    return <Navigate to="/login" state={{ from: location }} replace />;
  }
  
  return children;
}

// 使用
<Route path="/dashboard" element={<RequireAuth><Dashboard /></RequireAuth>} />

// 登录组件
import { useNavigate, useLocation } from 'react-router-dom';

function Login() {
  const navigate = useNavigate();
  const location = useLocation();
  const from = location.state?.from || '/';
  
  function handleLogin() {
    // 登录逻辑
    navigate(from, { replace: true });
  }
  
  return (
    <form onSubmit={handleLogin}>
      {/* 表单内容 */}
      <button type="submit">登录</button>
    </form>
  );
}

实战练习

练习1:基本路由配置

jsx
// src/App.jsx
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Contact from './pages/Contact';
import NotFound from './pages/NotFound';

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/about">关于</Link>
        <Link to="/contact">联系我们</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/contact" element={<Contact />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

// src/pages/Home.jsx
function Home() {
  return <h1>首页</h1>;
}

export default Home;

// src/pages/About.jsx
function About() {
  return <h1>关于我们</h1>;
}

export default About;

// src/pages/Contact.jsx
function Contact() {
  return <h1>联系我们</h1>;
}

export default Contact;

// src/pages/NotFound.jsx
import { Link } from 'react-router-dom';

function NotFound() {
  return (
    <div>
      <h1>404</h1>
      <p>页面未找到</p>
      <Link to="/">返回首页</Link>
    </div>
  );
}

export default NotFound;

练习2:嵌套路由

jsx
// src/App.jsx
import { BrowserRouter, Routes, Route, Link, Outlet } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import Dashboard from './pages/Dashboard';
import DashboardHome from './pages/DashboardHome';
import Profile from './pages/Profile';
import Settings from './pages/Settings';
import NotFound from './pages/NotFound';

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/about">关于</Link>
        <Link to="/dashboard">仪表盘</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
        <Route path="/dashboard" element={<Dashboard />}>
          <Route index element={<DashboardHome />} />
          <Route path="profile" element={<Profile />} />
          <Route path="settings" element={<Settings />} />
        </Route>
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

// src/pages/Dashboard.jsx
import { Link, Outlet } from 'react-router-dom';

function Dashboard() {
  return (
    <div>
      <h1>仪表盘</h1>
      <nav>
        <Link to="/dashboard">首页</Link>
        <Link to="/dashboard/profile">个人资料</Link>
        <Link to="/dashboard/settings">设置</Link>
      </nav>
      <Outlet />
    </div>
  );
}

export default Dashboard;

// src/pages/DashboardHome.jsx
function DashboardHome() {
  return <h2>仪表盘首页</h2>;
}

export default DashboardHome;

// src/pages/Profile.jsx
function Profile() {
  return <h2>个人资料</h2>;
}

export default Profile;

// src/pages/Settings.jsx
function Settings() {
  return <h2>设置</h2>;
}

export default Settings;

练习3:路由参数和查询参数

jsx
// src/App.jsx
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
import Home from './pages/Home';
import User from './pages/User';
import Search from './pages/Search';
import NotFound from './pages/NotFound';

function App() {
  return (
    <BrowserRouter>
      <nav>
        <Link to="/">首页</Link>
        <Link to="/user/1">用户 1</Link>
        <Link to="/user/2">用户 2</Link>
        <Link to="/search?keyword=React">搜索 React</Link>
      </nav>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/user/:id" element={<User />} />
        <Route path="/search" element={<Search />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </BrowserRouter>
  );
}

export default App;

// src/pages/User.jsx
import { useParams } from 'react-router-dom';

function User() {
  const { id } = useParams();
  
  return <h1>用户 ID:{id}</h1>;
}

export default User;

// src/pages/Search.jsx
import { useSearchParams } from 'react-router-dom';

function Search() {
  const [searchParams, setSearchParams] = useSearchParams();
  const keyword = searchParams.get('keyword');
  const page = searchParams.get('page') || 1;
  
  function changePage(newPage) {
    setSearchParams({ keyword, page: newPage });
  }
  
  return (
    <div>
      <h1>搜索结果</h1>
      <p>关键词:{keyword}</p>
      <p>页码:{page}</p>
      <button onClick={() => changePage(1)}>第 1 页</button>
      <button onClick={() => changePage(2)}>第 2 页</button>
      <button onClick={() => changePage(3)}>第 3 页</button>
    </div>
  );
}

export default Search;

通过本章节的学习,你已经掌握了 React Router v6 的基本使用方法。React Router 是构建单页面应用的核心工具,掌握它对于开发现代 React 应用至关重要。

© 2026 编程马·菜鸟教程 版权所有