React Router 6的学习

安装react-router-dom

npm i react-router-dom

支持不同的路由创建

createBrowserRouter

特点

  1. 推荐使用的方式,基于 HTML5 的 History API
  2. 支持用户友好的 URL,无需 #
  3. 适用于生产环境的绝大多数场景。

适用

使用现代浏览器,支持 pushState 和 replaceState 的情况

应用

import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Home from "../views/Home";
import About from "../views/About";
import ErrorPage from "../views/ErrorPage";

const router = createBrowserRouter([
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
  {
    path: "*", // 404 页面
    element: <ErrorPage />,
  },
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

tips

  1. 需要服务器支持,确保非根路径的页面请求被正确处理(常见问题是刷新后出现 404)
  2. 部署时,服务器通常需要配置以处理 SPA 应用

createHashRouter

特点

  1. URL 使用 #,如 http://example.com/#/about
  2. 不依赖服务器配置,适合快速开发和简单项目。
  3. 不推荐,因为 URL 不够优雅,且 SEO 支持较差

场景

  1. 静态站点部署(如 GitHub Pages)。
  2. 不支持 History API 的环境。

应用

import { createHashRouter, RouterProvider } from "react-router-dom";
import Home from "../views/Home";
import About from "../views/About";

const router = createHashRouter([
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

tips

  1. 无需服务器配置,但不适合对 URL 有美观或 SEO 要求的项目

createMemoryRouter

特点

  1. 不依赖浏览器环境,维护自己的内存中的路由栈。
  2. URL 不显示在浏览器地址栏
  3. 常用于非浏览器环境(如 React Native)或开发工具(如 Storybook)

场景

  1. 测试环境。
  2. 开发工具或需要自定义路由栈的应用

应用

import { createMemoryRouter, RouterProvider } from "react-router-dom";
import Home from "../views/Home";
import About from "../views/About";

const router = createMemoryRouter([
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
]);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

tips

  1. 开发中调试时有用,但生产环境通常不使用。
  2. URL 不可见,不适合需要 SEO 的场景

createStaticRouter

特点

  1. 用于服务器端渲染(SSR)。
  2. 基于预定义的静态路由配置。
  3. 无需用户交互,生成的路由用于服务端直接渲染

场景

  1. SSR(服务器端渲染)应用,例如使用 React Router 与 Next.js 或 Remix

应用

import { createStaticRouter, StaticRouterProvider } from "react-router-dom/server";
import Home from "../views/Home";
import About from "../views/About";

const router = createStaticRouter([
  { path: "/", element: <Home /> },
  { path: "/about", element: <About /> },
]);

function App() {
  return <StaticRouterProvider router={router} />;
}

export default App;

tips

  1. createStaticRouter需要结合服务器环境。
  2. 主要用于预渲染生成的 HTML,例如静态页面生成器或 SSR 服务。

总结

路由方式特点适用场景优缺点
createBrowserRouter基于 HTML5 History API,推荐使用现代浏览器应用,生产环境URL 美观,需服务器支持
createHashRouterURL 包含 #,不依赖服务器快速开发、简单项目,静态站点部署URL 不优雅,SEO 支持较差
createMemoryRouter路由存储在内存中,无需浏览器环境测试环境、开发工具,无浏览器场景不适用于生产环境,URL 不可见
createStaticRouter静态路由,用于 SSR 和静态页面生成服务器端渲染依赖服务端,无客户端交互

路由配置

  1. 使用 RoutesRoute 代替 React Router 5 的 Switch 和路由定义方式。
  2. 通过嵌套路由支持嵌套组件,可以实现更清晰的层次结构。
  3. path 属性定义路由路径,element 属性指定要渲染的组件
// App.jsx

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

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

function Home() {
  return <h1>Home Page</h1>;
}

function About() {
  return <h1>About Page</h1>;
}

function User({ id }) {
  return <h1>User Page for {id}</h1>;
}

动态路由

  1. 动态路由通过 :paramName 定义路径参数。
  2. 使用 useParams 钩子获取参数值。
  3. 动态路由使得可以根据 URL 参数渲染不同的内容,useParams 是获取路径参数的关键。
import { useParams } from 'react-router-dom';

function User() {
  const { id } = useParams(); // 获取路径中的 id 参数
  return <h1>User ID: {id}</h1>;
}

导航

  1. 使用 useNavigate 替代旧版本中的 useHistory
  2. useNavigate 提供更灵活的导航方式。
  3. navigate 可以接受路径字符串,也可以接受对象形式,适合处理编程式导航
import { useNavigate } from 'react-router-dom';

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

  const goToAbout = () => {
    navigate('/about');
  };

  return (
    <div>
      <h1>Home Page</h1>
      <button onClick={goToAbout}>Go to About</button>
    </div>
  );
}

嵌套路由

  1. 支持组件内部嵌套路由。
  2. 子路由通过 Outlet 渲染。
  3. Outlet 是子路由的占位符,嵌套路由更适合复杂布局。
import { Outlet, Link } from 'react-router-dom';

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <nav>
        <Link to="profile">Profile</Link>
        <Link to="settings">Settings</Link>
      </nav>
      <Outlet /> {/* 渲染子路由 */}
    </div>
  );
}

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="dashboard" element={<Dashboard />}>
          <Route path="profile" element={<Profile />} />
          <Route path="settings" element={<Settings />} />
        </Route>
      </Routes>
    </Router>
  );
}

重定向

  1. 使用 Navigate 组件进行页面重定向。
  2. 可在组件渲染时动态重定向。
  3. Navigate 是一个 JSX 组件,用于在路由中实现条件跳转
import { Navigate } from 'react-router-dom';

function ProtectedRoute({ isAuth, children }) {
  return isAuth ? children : <Navigate to="/login" />;
}

function App() {
  const isAuth = false; // 假设用户未登录

  return (
    <Router>
      <Routes>
        <Route
          path="/protected"
          element={
            <ProtectedRoute isAuth={isAuth}>
              <ProtectedPage />
            </ProtectedRoute>
          }
        />
        <Route path="/login" element={<Login />} />
      </Routes>
    </Router>
  );
}

数据加载

  1. React Router 6.4+ 引入了 loaderuseLoaderData,用于预加载路由数据。
  2. 支持异步加载,优化页面渲染体验。
  3. loader 提供异步数据加载,提升数据获取的灵活性,useLoaderData 获取加载的数据。
import { createBrowserRouter, RouterProvider, useLoaderData } from 'react-router-dom';

function UserProfile() {
  const data = useLoaderData(); // 获取预加载的数据
  return <h1>User Name: {data.name}</h1>;
}

const router = createBrowserRouter([
  {
    path: "/user/:id",
    element: <UserProfile />,
    loader: async ({ params }) => {
      const response = await fetch(`/api/user/${params.id}`);
      return response.json();
    },
  },
]);

function App() {
  return <RouterProvider router={router} />;
}

路由懒加载

  1. 减少首屏加载时间,提高性能;按需加载组件,降低内存占用;提升用户体验,特别是对于大型应用。
  2. 首次加载某个路由可能会有短暂延迟;如果 fallback 设计不当,可能导致用户体验下降;对 SEO 不友好,需配合服务器端渲染(SSR)解决。
  3. React.lazy(() => import('./ComponentPath')) 实现组件按需加载。
  4. Suspense用于显示加载状态(如 Loading...)直到懒加载组件加载完成
import React from "react";

const Home = React.lazy(() => import("../views/Home"));
const About = React.lazy(() => import("../views/About"));
const Dashboard = React.lazy(() => import("../views/Dashboard"));

const routes = [
  {
    path: "/",
    element: (
      <React.Suspense fallback={<div>Loading...</div>}>
        <Home />
      </React.Suspense>
    ),
  },
  {
    path: "/about",
    element: (
      <React.Suspense fallback={<div>Loading...</div>}>
        <About />
      </React.Suspense>
    ),
  },
  {
    path: "/dashboard",
    element: (
      <React.Suspense fallback={<div>Loading...</div>}>
        <Dashboard />
      </React.Suspense>
    ),
  },
];

export default routes;
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import routes from "./routes";

const router = createBrowserRouter(routes);

function App() {
  return <RouterProvider router={router} />;
}

export default App;

路由保护

  1. 使用高阶组件模式或条件渲染实现路由保护。
  2. 常与 Navigate认证逻辑结合。
function ProtectedRoute({ isAuth, children }) {
  return isAuth ? children : <Navigate to="/login" />;
}

错误处理

  1. 支持 errorElement 处理路由级别的错误
const router = createBrowserRouter([
  {
    path: "/",
    element: <Home />,
    errorElement: <ErrorPage />, // 错误处理组件
  },
]);

function ErrorPage() {
  return <h1>Something went wrong!</h1>;
}

综合案例

src/
├── router/
│   └── index.jsx  // 路由配置
├── views/
│   ├── Home.jsx   // 首页
│   ├── Login.jsx  // 登录页
│   ├── Content.jsx  // 内容页 (嵌套路由)
│   ├── ErrorPage.jsx // 错误页面
│   └── Protected.jsx // 受保护的页面
├── App.jsx        // 应用入口
└── main.jsx       // 渲染入口
// src/router/index.jsx
import { createBrowserRouter } from "react-router-dom";
import Home from "../views/Home";
import Login from "../views/Login";
import ErrorPage from "../views/ErrorPage";
import Content from "../views/Content";
import Protected from "../views/Protected";
import { Navigate } from "react-router-dom";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Navigate to="/home" replace />, // 重定向到 /home
  },
  {
    path: "/home",
    element: <Home />,
    errorElement: <ErrorPage />,
    children: [
      {
        path: "content",
        element: <Content />,
      },
    ],
  },
  {
    path: "/login",
    element: <Login />,
    errorElement: <ErrorPage />,
  },
  {
    path: "/protected",
    element: <ProtectedRoute>
      <Protected />
    </ProtectedRoute>,
    errorElement: <ErrorPage />,
  },
  {
    path: "*", // 404 页面
    element: <ErrorPage />,
  },
]);

// 模拟受保护的路由
function ProtectedRoute({ children }) {
  const isAuthenticated = false; // 假设用户未登录
  return isAuthenticated ? children : <Navigate to="/login" replace />;
}

export default router;

页面组件:src/views

// Home.jsx
import { Outlet, Link } from "react-router-dom";

function Home() {
  return (
    <div>
      <h1>Home Page</h1>
      <nav>
        <Link to="/home/content">Go to Content</Link>
        <Link to="/protected">Go to Protected Page</Link>
      </nav>
      <Outlet /> {/* 嵌套路由 */}
    </div>
  );
}

export default Home;
//Login.jsx
import { useNavigate } from "react-router-dom";

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

  const handleLogin = () => {
    // 模拟登录操作
    alert("Logged in!");
    navigate("/home"); // 登录后跳转到首页
  };

  return (
    <div>
      <h1>Login Page</h1>
      <button onClick={handleLogin}>Login</button>
    </div>
  );
}

export default Login;
//Content.jsx
function Content() {
  return <h1>Content Page</h1>;
}

export default Content;
//Protected.jsx
function Protected() {
  return <h1>Protected Page: You are authenticated!</h1>;
}

export default Protected;
//ErrorPage.jsx
function ErrorPage() {
  return <h1>404 Not Found</h1>;
}

export default ErrorPage;
// src/App.js
import { RouterProvider } from "react-router-dom";
import router from "./router";

function App() {
  return (
    <div>
      <RouterProvider router={router} />
    </div>
  );
}

export default App;
// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

效果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/934862.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

光猫开DMZ教程

本教程以移动光猫未例&#xff0c;具体操作以实际光猫为准 1、登录移动光猫管理后台 打开浏览器&#xff0c;在浏览器地址栏输入移动光猫登录管理地址192.168.1.1或者tplogin.cn 按“回车键”打开登录页面&#xff0c;然后输入路由器管理密码登录。 移动光猫登录页面 超级密…

图像的像素的存储结构:线性结构和二维数组

图像的像素的存储结构 无论是灰度图像还是RGB图像&#xff0c;当它们被读取到内存中时&#xff0c;通常也是以线性结构存储的。 这是因为计算机内存本质上是一维的地址空间&#xff0c;所有数据都是按照线性顺序存储在内存中的。 然而&#xff0c;在程序中处理这些图像时&am…

重庆轨道交通4号线寸滩地铁站自动化监测

1. 项目概述 本次项目位于重庆市轨道交通4号线中江北区寸滩站&#xff0c;轨道交通4号线是中国重庆市第八条开通运营的城市轨道交通&#xff0c;识别色为太阳橙。寸滩地处江北区中部&#xff0c;东与铁山坪街道毗邻&#xff0c;南与南岸区隔江相望&#xff0c;西与江北城中央商…

jQuery漏洞——CVE-2020-11022/CVE-2020-11023,保姆篇---春不晚

漏洞号&#xff1a;CVE-2020-11022/CVE-2020-11023 漏洞概况及影响 该类风险为应用安全缺陷类DXSS攻击&#xff0c;攻击者可以利用该漏洞注入恶意脚本代码&#xff0c;并在受害者的浏览器上执行。将导致受害者的个人信息泄露、账户被劫持、会话被劫持等安全问题。 一、漏洞版…

十五、K8s计划任务JobCronJob

K8s计划任务CronJob&Job 一、Job可以干什么 Job 控制器用于管理 Pod 对象运行一次性任务,比方说我们对数据库备份,可以直接在 k8s 上启动一个 mysqldump 备份程序,也可以启动一个 pod,这个 pod 专门用来备份用的,备份结束 pod 就可以终止了,不需要重启,而是将 Pod…

[入门一]C# webApi创建、与发布、部署、api调用

一.创建web api项目 1.1、项目创建 MVC架构的话&#xff0c;它会有view-model-control三层&#xff0c;在web api中它的前端和后端是分离的&#xff0c;所以只在项目中存在model-control两层 1.2、修改路由 打开App_Start文件夹下&#xff0c;WebApiConfig.cs ,修改路由&…

谷歌浏览器的隐私审查功能详解

随着互联网的发展&#xff0c;用户对隐私保护的关注日益增加。作为全球最受欢迎的浏览器之一&#xff0c;谷歌浏览器提供了多种隐私审查功能&#xff0c;帮助用户更好地管理和保护他们的在线隐私。本文将详细介绍如何查看Chrome浏览器的事件日志、更改标签页的打开顺序以及查看…

scala的正则表达式3

贪婪模式与非贪婪模式 1.贪婪模式 贪婪模式是正则表达式的默认行为。在这种模式下&#xff0c;量词&#xff08;如*、、?、{n,m}&#xff09;会尝试匹配尽可能多的字符。例如&#xff0c;正则表达式".*"会匹配任意数量的任意字符&#xff0c;包括空字符。 2非贪婪…

HNSW 分布式构建实践

作者&#xff1a;魏子敬 一、背景 随着大模型时代的到来&#xff0c;向量检索领域面临着前所未有的挑战。embedding 的维度和数量空前增长&#xff0c;这在工程上带来了极大的挑战。智能引擎事业部负责阿里巴巴搜推广及 AI 相关工程系统的设计和建设&#xff0c;我们在实际业务…

Windows 11 12 月补丁星期二修复了 72 个漏洞和一个零日漏洞

微软于 2024 年 12 月为 Windows 11 发布的补丁星期二修复了其产品生态系统中的 72 个漏洞&#xff0c;包括 Windows 通用日志文件系统驱动程序中一个被积极利用的零日漏洞。 这个严重漏洞可以通过基于堆的缓冲区溢出授予攻击者系统权限&#xff0c;使其成为此版本中优先级最高…

从模型到视图:如何用 .NET Core MVC 构建完整 Web 应用

MVC模式自出现以来便成为了 Web 开发的基石&#xff0c;它通过将数据、业务逻辑与用户界面分离&#xff0c;使得应用更加清晰易于维护&#xff0c;然而随着前端技术的飞速发展和框架如 React、Vue、Angular 等的崛起&#xff0c;许多开发者开始倾向于前后端分离的方式&#xff…

深度学习详解

深度学习&#xff08;Deep Learning&#xff0c;DL&#xff09;是机器学习&#xff08;Machine Learning&#xff0c;ML&#xff09;中的一个子领域&#xff0c;利用多层次&#xff08;深层&#xff09;神经网络来自动从数据中提取特征和规律&#xff0c;模仿人脑的神经系统来进…

nmap详解

Nmap&#xff08;Network Mapper&#xff09;是一个开放源代码的网络探测和安全审核的工具。由于它的功能强大&#xff0c;被广泛应用于网络安全领域。以下是Nmap的一些主要功能及其在实战中的应用举例。 Nmap的主要功能&#xff1a; 端口扫描&#xff1a;检测目标主机上开放…

Tina Linux如何enable开机LOGO

想要在Tina Linux开机的时候显示开机LOGO&#xff0c;我们需要进行如下几步工作&#xff1a; 在Uboot设备树中添加对应的屏幕设备树节点.修改Uboot配置&#xff0c;让其在开机时自动加载LOGO到屏幕上.在boot-resource分区中添加对应的启动LOGO图片&#xff0c;并命名为bootlog…

SpringBoot常见的注解

Spring Boot 常见注解详解 在 Spring Boot 开发中&#xff0c;注解是简化开发过程和提高效率的核心工具。通过使用各种注解&#xff0c;我们可以实现依赖注入、配置管理、Web 开发、数据访问等功能。以下是一些常见的 Spring Boot 注解&#xff0c;并对每个注解的作用进行了详…

使用 Python 爬取某网站简历模板(bs4/lxml+协程)

使用 Python 爬取站长素材简历模板 简介 在本教程中&#xff0c;我们将学习如何使用 Python 来爬取站长素材网站上的简历模板。我们将使用requests和BeautifulSoup库来发送 HTTP 请求和解析 HTML 页面。本教程将分为两个部分&#xff1a;第一部分是使用BeautifulSoup的方法&am…

【QGIS入门实战精品教程】4.12:QGIS创建标识码(BSM)字段并生成标识码

文章目录 一、加载实验数据二、生成BSM三、说明一、加载实验数据 加载配套实验数据包(订阅专栏后,从私信查收)中的4.12.rar中的自然幢数据,如下图所示: 打开属性表,查看属性表中的BSM效果: BSM字段说明:字符串,10位长度,以1开头,从1开始的连续序号结尾,总长度为10…

【GL009】C/C++总结(一)

自查目录 1. typedef 和 #define 的区别 2. const 、volatile 和 static 的区别 3. const修饰指针 4. 数组指针和指针数组 5. 函数指针和指针函数 6. C/C内存管理 6.1 内存分布图解 6.2 C语言中的内存分配方式 6.3 堆&#xff08;Heap&#xff09;和栈&#xff08;Sta…

Synchronizad优化原理(JUC)

目录 java对象头一&#xff1a;Monitor二&#xff1a;sychronized的优化轻量级锁&#xff08;轻量级锁&#xff09;锁膨胀&#xff08;重量级锁&#xff09;&#xff08;重量级锁&#xff09;锁自旋偏向锁&#xff08;比轻量级锁更轻量&#xff09;偏向锁状态如何撤销偏向锁批量…

Android显示系统(08)- OpenGL ES - 图片拉伸

Android显示系统&#xff08;02&#xff09;- OpenGL ES - 概述 Android显示系统&#xff08;03&#xff09;- OpenGL ES - GLSurfaceView的使用 Android显示系统&#xff08;04&#xff09;- OpenGL ES - Shader绘制三角形 Android显示系统&#xff08;05&#xff09;- OpenGL…