最近使用了一下react-router@6 版本感觉有很大的改动,记录一下。

React Router v6 makes heavy use of React hooks, so you'll need to be on React 16.8 or greater before attempting the upgrade to React Router v6. The good news is that React Router v5 is compatible with React >= 15, so if you're on v5 (or v4) you should be able to upgrade React without touching any of your router code.

官网给出的原文上面说的很清楚了,在 6 版本上使用了React Hooks写法,说明不支持class类来写。并且要求react版本在16.8以上。如果想兼容class组件 以及 react@15使用只能用react-router@5版本

安装

D:\your_project> npm i react-router-dom@6
# or
D:\your_project> yarn add react-router-dom@6
# or
D:\your_project> cnpm i react-router-dom@6

变化

SwitchRoutes

在 v5 版本中必须明确的说明嵌套的的路由和链接,那么就要获取父路由的属性等等。在 v6 版本则不需要,因为路径是相对的。案例如下:

// react-router-dom v5.1
import {
BrowserRouter,
Switch,
Route,
Link,
useRouteMatch,
} from "react-router-dom"; function App() {
return (
<BrowserRouter>
<Switch>
<Route exact path="/" children={<Home />} />
<Route path="/users" children={<Users />} />
</Switch>
</BrowserRouter>
);
} function Users() {
// 获取当前 router 匹配信息 { path:string , url: string , }
const match = useRouteMatch();
return (
<div>
<div className="link">
<Link to={`${match.url}/me`}>My Profile</Link>
</div>
<Switch>
{/* path = /users/me */}
<Route path={`${match.path}/me`}>
<OwnUserProfile />
</Route>
{/* path = /users/:id */}
<Route path={`${match.path}/:id`}>
<UserProfile />
</Route>
</Switch>
</div>
);
}

在 v6 版本后 再父组件里写的路径若无 /开头 都是相对父组件。案例如下:

// react-router-dom v6+
import {
BrowserRouter,
Routes,
Route,
Link,
} from "react-router-dom"; function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
{/* /users 下的所有路径 渲染 User组件 /user /user/* */}
<Route path="/users/*" element={<Users />} />
</Routes>
</BrowserRouter>
);
} function Users() {
return (
<div>
<nav>
{ /* to = /users/me */ }
<Link to="me">My Profile</Link>
</nav>
{/* 子组件 path 直接相对父组件 */}
<Routes>
{/* /user/me */}
<Route path="me" element={<OwnUserProfile />} />
{/* /user/:id */}
<Route path=":id" element={<UserProfile />} />
</Routes>
</div>
);

Route

  • Route Props.path

是相对的,它们会自动在父路由的路径和 URL 上构建。

<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="users" element={<Users />}>
{/* /user/me */}
<Route path="me" element={<OwnUserProfile />} />
{/* /user/:id */}
<Route path=":id" element={<UserProfile />} />
</Route>
</Routes>
</BrowserRouter>
  • Route (Props.component | Props.render | Props.children) 废弃 -> 使用 Props.element

在 v5 版本 路由可以使用 三种属性来挂载组件,但是在 v6 版本 只有一种 就是 element属性。

// react-router-dom v5.x
function Page() {
return <div> page 组件 </div>;
} // 使用 component 挂载组件
<Route path="/page" component={Page} />; // 使用 render 挂载组件
<Route
path="/page"
render={(routerProps) => <Page routerProps={routerProps} />}
/>; // 使用 children 挂载组件
<Route path="/page" children={<Page />} />; <Route path="/page">
<Page />
</Route>;

Redirect (移除)

在 v5 版本中 <Switch> 里 使用 <Redirect> 组件进行路由重定向。

// v5.x

// any code ...
<Switch>
<Route path="/user" children={<User />} />
</Switch>; function User({ userInfo }) {
if (!userInfo) {
// 重定向 到 登录页
return <Redirect to="/login" />;
}
return <div>User Page</div>;
}

在 v6 版本中 将使用 Navigation

// v6.x

// any code ...
<Switch>
<Route path="/user" children={<User />} />
</Switch>; function User({ userInfo }) {
if (!userInfo) {
// 重定向 到 登录页
return <Navigation to="/login" />;
}
return <div>User Page</div>;
}

Switch (移除)

在 v5 版本中 用 <Switch>组件包裹 <Route> 路由组件, 现在改用 <Routes>

// v5.x
<Switch>
<Route path="/" children={<Home />} />
<Route path="/user" children={<User />} />
</Switch> // v6.x
<Routes>
<Route path="/" element={<Home />} />
<Route path="/user" element={<User />} />
</Routes>

Link

Link 组件主要用于路由跳转,在 v5 版本 Linkto 属性是根据当前 url。举例:

// 当前 路由路径 /user
<Link to="me" /> // render <a href="/me" >...</a> // 当前 路由路径 /user/
<Link to="me" /> // render <a href="/user/me" >...</a>

而在 v6 版本中 如果LinkRoute里渲染 to 属性是根据当前<Route>路由的匹配的 url;如果不在Route组件里挂载的,则是根据 BrowserRouter.basename 渲染 跳转路径,默认/

// v6.x
import { BrowserRouter, Link, Outlet, Route, Routes } from "react-router-dom";
<BrowserRouter>
<Link to=""> go Home</Link> | <Link to="user"> go user</Link>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/user" element={<User />}>
<Route path=":id" element={<Person />} />
</Route>
</Routes>
</BrowserRouter>; function Home() {
return (
<div>
<h1>Home page</h1>
</div>
);
}
function User() {
return (
<div>
<h1>User page</h1>
<Link to="..">go Home</Link>
<Link to="abc">go User abc</Link>
<hr />
<Outlet />
</div>
);
} function Person() {
return (
<div>
<h1>User abc page</h1>
<Link to="..">go user</Link>
<Link to="../..">go Home</Link>
</div>
);
}

如果你把 url 看作文件路径,你发现 Linkto 相当于 cd 跳转。

<Route path="app">
<Route path="dashboard">
<Route path="stats" />
</Route>
</Route>
<Link to="stats"/> // => <a href="/app/dashboard/stats">
<Link to="../stats"/> // => <a href="/app/stats">
<Link to="../../stats"/> // => <a href="/stats">
<Link to="../../../stats"/> // => <a href="/stats">

假设当前的文件路径为 /app/dashboard

cd stats                        # pwd is /app/dashboard/stats
cd ../stats # pwd is /app/stats
cd ../../stats # pwd is /stats
cd ../../../stats # pwd is /stats

NavLink

Props.exact 命名为 Props.end,删除Props.activeClassName,Props.activeStyle 使用函数返回style,className

// v5.x
const style = { color : "red" }
<NavLink to="/user" exact />
<NavLink to="/user" activeClassName="active-link" />
<NavLink to="/user" activeStyle={style} /> // v6.x
const getCls = ({ isActive }) => isActive ? "link" : "ative link";
const getStyle = ({ isActive }) => ({ color: isActive ?'red': 'blue' })
<NavLink to="/user" end /> // 精确匹配
<NavLink to="/user" className={getCls} />
<NavLink to="/user" activeStyle={getStyle} />

useRouteMatch (替换) useMatch

useMatch api

新增

Navigate 跳转路由组件

<Navigate> 组件和 useNavigate hooks api 拥有一样的用法。在函数组件使用 useNavigate api,而在 class 组件,可以使用 Navigate 组件进行挂载跳转路由。

interface NavigateProps {
to: To;
replace?: boolean;
state?: any;
}
class User extends React.Component {
render() {
const { userInfo } = this.props;
if (!userInfo) {
return <Navigate to="/login" replace />;
}
return <div>User</div>;
}
}

Outlet 路由视图组件

Route 下有子 Route 的时候 需要使用 Outlet 显示子路由内容。

案例

useLocation hooks

获取当前路由位置对象。如果您想在当前位置更改时执行一些副作用,这可能很有用。

import { useEffect } from "react"
import { useLocation } from 'react-router-dom'; function App() {
let location = useLocation(); useEffect(() => {
// do something
}, [location]); return (
// ...
);
}

useNavigate hooks

调用返回一个函数,该函数调用第一个参数为string类型 与 <Link> to 属性 效果一样,为number类型,在历史记录堆栈中传递要访问的增量。第二个参数 与 <Link>state,replace类型相同。 替代了 v5 版本中的 history 对象

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

function App(){
const navigate = useNavigate();
const submit = (data)=>{
api(data).then(res=>{
navigate("/user")
})
}
const back = ()=>{
navigate(-1) // 后退一页
}
return (
// ...
)
}

useParams hooks

获取路由:匹配的信息,返回当前 URL 中与 匹配的动态参数的键/值对的对象。

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

function Person(){
const { id } = useParams() // path = /user/:id => current url = /user/1 console.log(id) // 1
return (
// ....
)
}

useRoutes hooks

使用数组来定义路由。返回路由组件。

import { useRoutes } from "react-router-dom";

const routes = [
{
path: "/",
element: <Home />,
children: [
{
path: "/test",
element: <Test />,
},
],
},
{
path: "*",
element: <NotFound />,
},
]; function App() {
const router = useRoutes(routes);
return router;
}

useSearchParams hooks

用于读取和设置 url 的query部分,返回和 react useState hooks 一样。每次searchParams修改相当于路由 push 一次。

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

// current url => /
function App() {
const [searchParams, setSearchParams] = useSearchParams();
const setQueryId = () => {
// url change => /?id=2&name=test
setSearchParams({
id: 2,
name: "test",
});
};
return (
<div>
<h1> current query id :{searchParams.get("id")}</h1>
<button onClick={setQueryId}>set id</button>
</div>
);
}
  • searchParams

    • searchParams.get(str) 返回 string | null

      获取 url 的 query 第一个匹配上的的str值.例如/user?id=1=> searchParams.getAll('id') 返回值为为 '1'

    • searchParams.getAll(str) 返回 string[]

      获取 url 的 query 所有的str值.例如/user?id=1&id=2=> searchParams.getAll('id') 返回值为 ['1','2']

  • setSearchParams

    修改当前 url query 部分。相当于路由跳转了。你可以使用第二个参数,进行是否推入history栈。例如:setSearchParams({ id : 2 },{ replace : true })相当于history.replace({currentUrl}/?id=2)

react-router@6 版本初体验的更多相关文章

  1. React Router 4.x 开发,这些雷区我们都帮你踩过了

    前言 在前端框架层出不穷的今天,React 以其虚拟 DOM .组件化开发思想等特性迅速占据了主流位置,成为前端开发工程师热衷的 Javascript 库.作为 React 体系中的重要组成部分:Re ...

  2. React Router 4.0 体验

    React Router 4.0 (以下简称 RR4) 已经正式发布,它遵循React的设计理念,即万物皆组件.所以 RR4 只是一堆 提供了导航功能的组件(还有若干对象和方法),具有声明式(声明式编 ...

  3. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  4. 【Knockout.js 学习体验之旅】(1)ko初体验

    前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...

  5. 基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    基于 Webpack & Vue & Vue-Router 的 SPA 初体验 本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com ...

  6. Taro开发微信小程序的初体验

    了解Taro 听说Taro是从几个星期前开始的,在一次饭桌上,一个小伙伴说:"Hey, 你听说了Taro么,听说只需要写一套程序就可以生成H5,小程序以及RN的代码模板,并且类似于React ...

  7. [Web 前端] React Router v4 入坑指南

    cp from : https://www.jianshu.com/p/6a45e2dfc9d9 万恶的根源 距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子 ...

  8. 从 React Router 谈谈路由的那些事

    React Router 是专为 React 设计的路由解决方案,在使用 React 来开发 SPA (单页应用)项目时,都会需要路由功能,而 React Router 应该是目前使用率最高的. Re ...

  9. Handlebars的基本用法 Handlebars.js使用介绍 http://handlebarsjs.com/ Handlebars.js 模板引擎 javascript/jquery模板引擎——Handlebars初体验 handlebars.js 入门(1) 作为一名前端的你,必须掌握的模板引擎:Handlebars 前端数据模板handlebars与jquery整

    Handlebars的基本用法 使用Handlebars,你可以轻松创建语义化模板,Mustache模板和Handlebars是兼容的,所以你可以将Mustache导入Handlebars以使用 Ha ...

随机推荐

  1. javax.net.ssl.sslhandshakeException:sun.security.validator.validatorException:PKIX path buildind failed

    前段时间开发的一个需求,需要通过图片URL获取图片的base64编码,测试的时候使用的是百度图片的url,测试没有问题,但是发布后测试时报如下错: javax.net.ssl.sslhandshake ...

  2. Elasticsearch 在部署时,对 Linux 的设置有哪些优化方法 ?

    1.关闭缓存 swap; 2.堆内存设置为:Min(节点内存/2, 32GB); 3.设置最大文件句柄数: 4.线程池+队列大小根据业务需要做调整: 5.磁盘存储 raid 方式--存储有条件使用 R ...

  3. java-面向对象相关

    public class DemoMethodOverload { public static void main(String[] args) { int[] array = new int[]{1 ...

  4. 信号量,semaphore源代码之我见

    信号量,Semaphore,一个限定访问线程数量的工具类,属于并发包java.util.concurrent 里面的类. Semaphore,内部提供了构造方法(包含默认的非公平信号量构造方法,已经可 ...

  5. 遇到过的问题之“解决 No qualifying bean of type 问题”

    1.问题 解决 No qualifying bean of type 问题 2.思路: 1 检查是否添加了对应注解 2 检查配置是否正确,扫描包名, 类名及id是否正确 一 . 传统SSM项目 ssm ...

  6. 8_LQR 控制器_状态空间系统Matlab/Simulink建模分析

    再线性控制器中讲到: 举例说明(线性控制器中的一个例子)博客中有说明 在matlab中:使用lqr求解K1.K2 这里希望角度(即x1)能迅速变化,所以Q矩阵中Q11为100,并没有关心角速度(dot ...

  7. C语言中的bool类型 stdbool.h

    C语言的C99标准中已经可以使用bool类型了,但有些小伙伴可能受制于编译器等原因还无法使用,我就从最新版的VS2019 中,找到了stdbool.h这个头文件的定义,其实就是一堆宏的定义,代码如下: ...

  8. 使用Node.js版本管理器

    使用Node.js版本管理器 完全卸载Node.js 清除Package缓存:npm cache clean --force 卸载Node.js:wmic product where caption= ...

  9. H5移动端开发

    开发前准备 环境: Node.js LTS版本 git 最新版 文档: 本项目技术栈基于 ES2016 VueJS vux 快速开始 1.克隆项目 git clone https://gitee.co ...

  10. ES6-11学习笔记--Iterator

    迭代器 Iterator 是一种接口机制,为各种不同的数据结构提供统一访问的机制 主要供for...of消费 一句话:不支持遍历的数据结构"可遍历"   具备Symbol.iter ...