React Router v6:路由管理的最新进展

React Router v6 是 React 应用程序路由管理的一个重大更新,它引入了许多改进和简化,包括对嵌套路由的更友好处理,以及对钩子函数的使用。

2500G计算机入门到高级架构师开发资料超级大礼包免费送!

1. Routes 重构

在 v6 中,<Route> 组件被替换为 <Routes> 组件,后者用于包裹所有路由。此外,Switch 组件不再存在,因为 <Routes> 已经实现了类似于 Switch 的行为,只会匹配并渲染第一个匹配的路由。

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="/users/*" element={<Users />} /> {/* 通配符支持 */}</Routes></Router>);
}

2. 使用 element 属性

路由现在通过 element 属性指定要渲染的组件,而不是通过 componentrender 函数。

<Route path="/profile/:userId" element={<Profile />} />

3. Hook API

React Router v6 引入了新的钩子函数,如 useHistory, useLocation, useParams, 和 useNavigate,这些钩子允许在组件内部直接处理导航。

import { useParams } from 'react-router-dom';function Profile() {const { userId } = useParams();return <div>Profile of user {userId}</div>;
}

4. navigate 函数

useNavigate 钩子返回一个 navigate 函数,用于在组件内部导航。

import { useNavigate } from 'react-router-dom';function ProfileForm() {const navigate = useNavigate();const handleSubmit = (event) => {event.preventDefault();// 提交表单后导航到另一个页面navigate('/success', { replace: true }); // 替换当前历史记录};return <form onSubmit={handleSubmit}>...</form>;
}

5. 懒加载和代码分割

React Router v6 支持动态导入,这有助于实现代码分割,提高应用的加载速度。

<Route path="/lazy" element={import('./LazyComponent').then((mod) => mod.LazyComponent)} />

6. 404 页面

处理未找到的路由,可以设置一个通配符路由来捕获所有未匹配的路径。

<Route path="*" element={<Error404 />} />

7. 嵌套路由

嵌套路由的处理更加简洁,使用 Routes 和 Route 的组合即可。

function App() {return (<Router><Routes><Route path="/" element={<MainLayout />}><Route index element={<Home />} /><Route path="about" element={<About />} /><Route path="users" element={<Users />}><Route path=":userId" element={<User />} /></Route></Route><Route path="*" element={<Error404 />} /></Routes></Router>);
}

8. 路由保护和权限控制

在React Router v6中,可以使用 useEffectuseLayoutEffect 钩子以及 useNavigate 来实现路由保护,确保用户在登录后才能访问受保护的路由。

import { useNavigate, useLocation } from 'react-router-dom';function PrivateRoute({ children }) {const location = useLocation();const navigate = useNavigate();useEffect(() => {if (!isAuthenticated()) {navigate('/login', { replace: true });}}, [navigate]);return isAuthenticated() ? children : null;
}function App() {return (<Router><Routes><Route path="/" element={<PublicRoute><Home /></PublicRoute>} /><Route path="/dashboard" element={<PrivateRoute><Dashboard /></PrivateRoute>} /><Route path="/login" element={<Login />} /></Routes></Router>);
}

在这个例子中,isAuthenticated() 是一个假设的函数,检查用户是否已登录。如果用户未登录,他们将被重定向到登录页面。

9. 重定向和重定位

在 v6 中,可以使用 Navigate 组件来实现重定向。它类似于一个特殊的元素,会触发导航到指定的URL。

import { Navigate } from 'react-router-dom';function PrivateRoute({ children }) {if (!isAuthenticated()) {return <Navigate to="/login" replace />;}return children;
}

10. 路由参数和查询字符串

在 v6 中,你可以使用 useParams 钩子获取路由参数,使用 useLocation 获取查询字符串。

import { useParams, useLocation } from 'react-router-dom';function Profile() {const { userId } = useParams();const query = new URLSearchParams(useLocation().search);const searchParam = query.get('paramName');return <div>Profile of user {userId} with search param: {searchParam}</div>;
}

11. 自定义路由匹配

React Router v6 允许你通过 path-to-regexp 库自定义路由匹配规则,但通常情况下,标准的路径模式已经足够使用。

12. 高阶组件(HoC)

尽管 v6 中不再推荐使用高阶组件,但你仍然可以通过包装组件来实现特定逻辑,如路由保护。

function PrivateRoute({ children }) {if (!isAuthenticated()) {return <Navigate to="/login" replace />;}return <>{children}</>;
}function App() {return (<Router><Routes><Route path="/" element={<PublicRoute><Home /></PublicRoute>} /><Route path="/dashboard" element={<PrivateRoute><Dashboard /></PrivateRoute>} /><Route path="/login" element={<Login />} /></Routes></Router>);
}

13. 路由事件

React Router v6 提供了一些生命周期事件,如 useRouteMatchuseLocationuseHistoryuseNavigate。这些钩子可以帮助你在组件中监听路由变化并做出响应。

import { useLocation } from 'react-router-dom';function Navbar() {const location = useLocation();useEffect(() => {console.log(`Navigated to ${location.pathname}`);}, [location]);return /* ... */;
}

14. 路由配置的模块化

为了保持代码的整洁,你可以将路由配置分散到多个模块中,然后在主配置文件中导入并合并它们。

// routes/users.js
export default [{ path: '/users', element: <UsersList /> },{ path: '/users/:id', element: <UserProfile /> },
];// routes/admin.js
export default [{ path: '/admin/dashboard', element: <AdminDashboard /> },{ path: '/admin/users', element: <AdminUsers /> },
];// App.js
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import usersRoutes from './routes/users';
import adminRoutes from './routes/admin';function App() {return (<Router><Routes>{usersRoutes.map((route, index) => (<Route key={index} {...route} />))}{adminRoutes.map((route, index) => (<Route key={index} {...route} />))}{/* 错误页面或404页面 */}<Route path="*" element={<ErrorPage />} /></Routes></Router>);
}

15. 路由守卫(Guard)

你可以创建自定义的守卫函数来决定用户是否可以访问某个路由。这通常用于实现权限验证或数据预加载。

function requireAuth(nextState, replace) {if (!isAuthenticated()) {replace({pathname: '/login',state: { nextPathname: nextState.location.pathname },});}
}// 在路由中使用
<Route path="/protected" onEnter={requireAuth} component={ProtectedComponent} />

在 v6 中,可以使用 useEffect 或 useLayoutEffect 钩子来实现类似的功能。

16. 路由嵌套

虽然在 v6 中不再需要显式地包裹 Switch 组件,但嵌套路由的概念仍然存在。你可以通过在路由配置中嵌套 Routes 来实现。

function App() {return (<Router><Routes><Route path="/" element={<MainLayout />}><Route index element={<Home />} /><Route path="about" element={<About />} /><Route path="users" element={<Users />}><Route path=":userId" element={<User />} /></Route></Route><Route path="*" element={<Error404 />} /></Routes></Router>);
}

在这个例子中,/users/:userId 路由是在 /users 路由内部定义的,这意味着在访问 /users/someId 时,Users 组件会被渲染,同时 User 组件也会被渲染。

17. 自定义错误处理

React Router v6 不再提供全局错误处理,但你可以通过监听 window.onError 或使用自定义中间件来实现。

18. 代码分割和懒加载

React Router v6 与 Webpack 或其他打包工具很好地配合,可以实现代码分割和懒加载。你可以使用 import() 动态导入组件来实现这一点。

<Routepath="/lazy"element={import('./LazyComponent').then((mod) => mod.LazyComponent).catch((error) => <ErrorBoundary error={error} />)}
/>

19. 自定义路由组件

虽然 Route 组件在 v6 中已经非常简单,但你仍然可以创建自己的组件来扩展其功能,例如添加自定义的加载指示器。

20. 服务器端渲染(SSR)

React Router v6 支持服务器端渲染,但需要额外的配置和库,如 react-router-dom/serverreact-router-dom/browser

2500G计算机入门到高级架构师开发资料超级大礼包免费送!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes数据存储

1. 数据存储 容器的生命周期可能很短&#xff0c;会被频繁地创建和销毁。那么容器在销毁时&#xff0c;保存在容器中的数据也会被清除。这种结果对用户来说&#xff0c;在某些情况下是不乐意看到的。为了持久化保存容器的数据&#xff0c;kubernetes引入了Volume的概念。 Volu…

HTML-JavaWeb

目录 1.标题排版 2.标题样式 ​编辑 ​编辑 小结 3.超链接 4.正文排版 ​编辑​编辑​编辑5.正文布局 6.表格标签 7.表单标签 8.表单项标签 1.标题排版 ● 图片标签 :< img> src:指定图像的ur1(绝对路径/相对路径) width:图像的宽度(像素/相对于父元素的百…

【AD21】文件的整理

当所有文件输出完成后&#xff0c;需要对不同的文件去做一个整理&#xff0c;方便后续工作的交接。 在项目工程文件夹下新建名称为BOM、SMT、PRJ、Gerber和DOC的文件夹。 BOM文件夹存放BOM表发给采购人员。SMT文件夹存放装配图文件和坐标文件发给贴片厂。PRJ文件夹存放工程文件…

C++基础:多态

多态相关 多态继承重写父类的虚函数多态的体现,父类的引用指向子类对象的空间虚函数可以实现,也可以不实现,不实现必须要有初始值存在未定义的虚函数的类为抽象类.抽象类不能实例化对象;(animal父类不能实例化对象)如果父类中的函数非虚函数,则会调用父类中的函数//多态的体现…

汇凯金业:纸黄金和实物黄金的价格有什么区别

纸黄金和实物黄金的价格主要受到全球黄金市场行情的影响&#xff0c;二者的基础价格并无太大差异&#xff0c;但在具体交易时&#xff0c;可能会存在一些价格上的区别&#xff0c;这些差异主要来自以下几个方面&#xff1a; 交易费用与管理费&#xff1a;纸黄金交易通常需要支…

python xls格式转为xlsx格式

python 两个表格字段列名称值&#xff0c;对比字段差异-CSDN博客 import os import win32com.clientdef xls_to_xlsx(file_path, excel):"""将指定的xls文件转化为xlsx格式file_path: 文件路径excel: 代表Excel应用程序"""# 打开原始文档workbo…

【Java】IdentityHashMap 的使用场景

文章目录 前言1. Druid 应用场景2. IdentityHashMap 特性3. IdentityHashMap 同步化4. IdentityHashMap 处理key为空值后记 前言 最近有兴趣看一下 Druid 连接池怎么做连接管理的&#xff0c;看到一个类 IdentityHashMap &#xff0c;这里记录一下使用场景。 1. Druid 应用场…

代码随想录算法训练营第36期DAY41

DAY41 动态规划理论基础 还差闫氏分析法没学完。见B站收藏夹。 前两题学习初始化方式就好vector<int> dp(N1); 509斐波那契数 简单。 class Solution {public: int fib(int N) { if (N < 1) return N; int dp[2]; dp[0] 0; dp[…

plt画图中文乱码

1、使用font_manager的FontProperties解决 通过FontProperties来设置字符及大小&#xff0c;来解决中文显示的问题&#xff0c;代码如下&#xff1a; import matplotlib import matplotlib.pyplot as pltpath "..\simsun.ttc"#改成你自己的文件路径 font FontProp…

【物联网实战项目】STM32C8T6+esp8266/mqtt+dht11+onenet+uniapp

一、实物图 前端uniapp效果图&#xff08;实现与onenet同步更新数据&#xff09; 首先要确定接线图和接线顺序&#xff1a; 1、stm32c8t6开发板连接stlinkv2下载线 ST-LINK V2STM323.3V3.3VSWDIOSWIOSWCLKSWCLKGNDGND 2、ch340串口连接底座&#xff08;注意RXD和TXD的连接方式…

NSS题目练习4

[LitCTF 2023]1zjs 打开后是一个游戏&#xff0c;用dirsearch扫描&#xff0c;什么都没发现 查看源代码搜索flag&#xff0c;发现没有什么用 搜索php&#xff0c;访问 出现一堆符号&#xff0c;看样子像是jother编码 解码得到flag&#xff0c;要删掉[] [LitCTF 2023]Http pro …

37、Flink 的窗口函数(Window Functions)详解

窗口函数&#xff08;Window Functions&#xff09; a&#xff09;概述 定义了 window assigner 之后&#xff0c;需要指定当窗口触发之后&#xff0c;如何计算每个窗口中的数据&#xff0c; 即 window function。 窗口函数有三种&#xff1a;ReduceFunction、AggregateFunc…

嵌入式学习记录5.27(c++基础1)

目录 一.C和C的区别 二.输入输出流类 2.1输出cout 2.2输入cin 三.命名空间 2.1使用命名空间中的标识符 2.2命名空间中声明函数 2.3命名冲突问题 2.4匿名空间 2.5命名空间添加&#xff0c;嵌套&#xff0c;重命名 四.字符串的使用 4.1string类 4.2C风格和C风格字符串…

LeetCode27.移除元素

题目链接&#xff1a; 27. 移除元素 - 力扣&#xff08;LeetCode&#xff09; 思路分析&#xff1a;同样属于经典的双指针移动问题&#xff0c;要掌握固定的思路即可。 算法分析&#xff1a;这个题目可以这样处理&#xff0c;我们把所有非val 的元素都向前移动&#xff0c;把…

Java面试八股之线程池是怎么实现的

线程池是怎么实现的 线程池是一种基于池化技术的线程管理方式&#xff0c;通过预先创建一定数量的线程并保持在池中待命&#xff0c;从而在有任务来临时能够快速分配线程处理任务&#xff0c;而无需频繁创建和销毁线程&#xff0c;以此达到提升系统性能、减少资源消耗的目的。…

推荐《从零开始大模型开发与微调》

大模型是深度学习是当前AI和NLP研究与产业中最重要的方向之一。 本书用PyTorch 2.0作为学习大模型的基本框架&#xff0c;以ChatGLM为例详细讲解大模型的基本理论、算法、程序实现、应用实战以及微调技术&#xff0c;为读者揭示大模型开发技术。 《从零开始大模型开发与微调&…

两个数组的交集-力扣

想到的解法是使用两个哈希表&#xff0c;s1用来统计nums1中出现过的数字&#xff0c;然后遍历nums2数组&#xff0c;当能够在s1中查找到nums2的元素时&#xff0c;将这个元素添加到s2中&#xff0c;最后遍历s2&#xff0c;将其中的元素添加到返回数组中。 但最开始写时&#xf…

外星人存在与否......----小话外星人(1)

前一段时间&#xff0c;看了好多关于UFO、外星人、宇宙、远古外星人的视频和电子书&#xff0c;最后发现&#xff0c;这样的东西还是不要看多为好&#xff0c;搞得好像这些是真的似的&#xff0c;有时睡觉会被意外惊醒&#xff0c;想多了...... 1、外星人存在吗 不管有多少UFO的…

Windows10映射网络驱动器之后不显示映射盘

目录 背景解决步骤1、按 Windows R 打开运行2、打开注册表编辑器3、 System上新建-- DWORD(32bit)4、对新建的文件重命名5、将EnableLinkedConnections的数值改为16、退出注册表编辑器&#xff0c;重启系统。 知识扩展断开连接备份注册表 背景 目前有一台NAS服务器,和一台lin…

Vuex 页面刷新数据丢失怎么解决

当Vuex中的数据在页面刷新后丢失时&#xff0c;这通常是因为Vuex的状态数据是保存在运行内存中的&#xff0c;页面刷新会导致Vue实例重新加载&#xff0c;进而Vuex中的数据被重置为初始状态。为了解决这个问题&#xff0c;可以采取以下几种方法&#xff1a; 1. 使用浏览器的本…