React-Router V6 使用详解

146 阅读4分钟

React-Router V6 使用详解

React-Router 是 React 生态中最流行的路由解决方案之一,V6 版本带来了许多重大改进和简化。本文将全面介绍 React-Router V6 的核心概念、API 和使用方法。

一、React-Router V6 概述

React-Router V6 于 2021 年发布,相比 V5 更简单的 API 设计, 完全支持 React hooks、 、路由配置更加灵活 、移除了 <Switch> 组件,改用 <Routes> 、 相对路径和链接简化 、路由嵌套更直观

二、基本使用

安装

npm install react-router-dom@6
# 或
yarn add react-router-dom@6

核心组件说明

  • <BrowserRouter>:包裹整个react应用,提供基于 HTML5 history API 的路由管理。
  • <Routes>:替代了旧版本中的 <Switch>,用于包裹一组 <Route> 组件,并根据当前 URL 显示匹配的第一个子 <Route>
  • <Route>:定义路由映射关系
    • path:路由路径
    • element:匹配时渲染的组件(V5 中是 componentrender

具体使用(启用全局路由模式

创建一个react项目,在入口文件(如 index.jsmain.js),引入BrowserRouter并将应用组件包裹在 BrowserRouter 中。之后在的应用中,使用 RoutesRoute 组件来定义你的路由结构

main.jsx

import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.jsx";
import { BrowserRouter as Router } from "react-router-dom";

createRoot(document.getElementById("root")).render(
  <Router>
    <App />
  </Router>
);

App.jsx

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

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

function Home() {
  return (
      <h2>Home</h2>
  );
}
function About() {
  return (
      <h2>About</h2>
  );
}
function Users() {
  return (
      <h2>Users</h2>
  );
}

通过改变url即可切换不同的组件

三、路由导航

声明式导航

Link 和 NavLink

  • Link 提供了一个声明式的方式来导航到不同的页面。
  • NavLinkLink 的一个变体,当其目标路径与当前URL匹配时,可以自动添加样式类(如 activeClassName)。

使用 <Link><NavLink>

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

function Navigation() {
  return (
    <nav>
      <Link to="/">Home</Link>
      <NavLink 
        to="/about"
        style={({ isActive }) => ({ color: isActive ? 'red' : 'blue' })}
      >
        About
      </NavLink>
    </nav>
  );
}

<NavLink> 可以感知当前是否处于激活状态。

编程式导航

使用useNavigatehook返回一个函数,使用该函数在组件内部进行编程式导航。

使用 useNavigate hook:

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

function LoginButton() {
  const navigate = useNavigate();
  
  const handleLogin = () => {
    // 跳转到指定路径
    navigate('/dashboard');
    
    // 替换当前历史记录
    // navigate('/dashboard', { replace: true });
    
    // 带状态跳转
    // navigate('/dashboard', { state: { from: 'login' } });
  };
  
  return <button onClick={handleLogin}>Login</button>;
}

四、动态路由与参数

路径参数

假设你有一个用户详情页面,并且想要通过用户 ID 来访问该用户的详情信息,你可以这样做:

<Route path="users/:id" element={<UserDetail />} />

在这个例子中,:id 是一个动态参数。要访问这个参数,在你的 UserDetail 组件内可以使用 useParams 钩子来获取这个参数:

import { useParams } from 'react-router-dom';

function UserDetail() {
  const { id } = useParams();
  console.log(id)
  return <div>User ID: {id}</div>;
}

输入

http://localhost:5173/users/123

输出

123

通过查询参数传递

对于查询参数(即 URL 中的键值对,如 ?name=value&mode=edit),可以使用 useSearchParams 钩子来获取这些参数:

import { useSearchParams } from 'react-router-dom';

function ComponentWithQueryParams() {
  let [searchParams] = useSearchParams();
  
  let name = searchParams.get('name');
  let mode = searchParams.get('mode');
 
  return (
    <div>
      <p>Name: {name}</p>
      <p>Mode: {mode}</p>
    </div>
  );
}
function App() {
  return (
      <Routes>
        <Route path="/path" element={<ComponentWithQueryParams />} />
      </Routes>
  );
}

为了导航到包含查询参数的路径,你可以使用 useNavigate 或者 <Link> 组件,并将查询参数作为对象传递给 to 属性:

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

function NavigateButton() {
  let navigate = useNavigate();

  function handleClick() {
    navigate('/path', { search: '?name=value&mode=edit' });
  }

  return <button onClick={handleClick}>Go</button>;
}

五、嵌套路由

react-router-dom v6 开始,定义嵌套路由的方式有所变化,主要是通过 <Routes><Route> 组件来实现的。下面是一个简单的例子,演示如何设置嵌套路由:

假设你有一个应用布局如下:

  • 主页
  • 用户列表页
    • 单个用户的详情页

App中路由配置

在这个例子中,Users 组件将会渲染用户列表,而 UserProfile 组件会渲染单个用户的详情。:id 是一个动态参数,用于标识不同的用户。

import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Home from './Home';
import Users from './Users';
import UserProfile from './UserProfile';

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/users" element={<Users />}>
          {/* 嵌套路由 */}
          <Route path=":id" element={<UserProfile />} />
        </Route>
      </Routes>
    </Router>
  );
}

在父路Users由中使用 <Outlet>

为了让嵌套路由工作,父级路由组件(本例中的 Users 组件)需要使用 Outlet 来指定子路由应该在哪里渲

import { Outlet } from 'react-router-dom';

function Users() {
  return (
    <div>
      <h1>用户列表</h1>
      {/* 子路由将在这里渲染 */}
      <Outlet />
    </div>
  );
}

索引路由

索引路由是当父路由路径匹配时默认渲染的子路由

当进入访问 / 时,之间导航到<Route index element={} />

<Route path="/" element={<Users />}>
  <Route index element={<Like />} />
  <Route path="/stats" element={<Like />} />
</Route>

六、重定向

react-router-dom 中实现**重定向(Redirect)**是一个常见的需求,比如用户未登录时跳转到登录页、页面路径变更后的跳转、或者路由匹配失败时跳转到 404 页面等。

react-router-dom v6 及以上版本中,不再使用 Redirect 组件(v5 中可用),而是推荐使用新的方式:useNavigate 钩子 或 <Navigate> 组件。

使用 <Navigate> 组件:

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

function ProtectedRoute({ isLoggedIn, children }) {
  if (!isLoggedIn) {
    return <Navigate to="/login" replace />;
  }

  return children;
}

参数说明:

  • to:要跳转的目标路径,可以是字符串或对象。
  • replace:是否替换当前历史记录,默认为 false。设置为 true 时,用户无法通过“返回”按钮回到上一页。

使用 useNavigate 钩子(适用于逻辑跳转,如点击按钮后跳转)

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

function LoginPage() {
  const navigate = useNavigate();

  const handleLogin = () => {
    // 模拟登录成功
    const success = true;
    if (success) {
      navigate('/dashboard'); // 跳转到首页
    }
  };

  return (
    <div>
      <h2>登录页面</h2>
      <button onClick={handleLogin}>登录</button>
    </div>
  );
}