React-router升到v6了?

news/2024/7/15 18:07:31 标签: react.js, javascript, 前端

前言

之前一直负责老项目的迭代,而且很少关注router相关的代码,直到上个月公司开了一个新项目,当我着手开始配置路由时突然发现,嗯?Switch标签咋没了?Route里的component属性咋也没了。意识到不妙的我赶紧去翻了翻react router的文档,发现react router早就在21年底就偷偷升级到了v6且变更极大(嗯 这是一个悲伤的故事,现在甚至已经更新到了6.4.1)

之前的老项目的包版本是5.2的,要升级的话成本有点高,也懒得搞,就那样吧。但新项目肯定不能将就啊。那就整呗

正文

首先先说一下react-router和react-router-dom的区别,react-router实现了路由的核心功能,react-router-dom则是基于react-router,又加了在浏览器运行环境下的一些功能,比如把Link组件渲染成一个a标签,再比如HashRouter会使用window.location.hash和hashChange事件构建路由。一般在项目中只需要引入react-router-dom包即可。

npm install react-router-dom

BrowserRouter

新项目使用浏览器路由即BrowserRouter,要想在项目中使用React Router,需要App组件嵌套进BrowserRouter组件中。

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

Routes和Route

我们使用Route组件来定义路由,并使用Routes包裹。

Route组件接收两个props:

  • path?: string | 页面url
  • element?: React.ReactNode |当前url需要加载的元素
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/teams/:id" element={<Teams />} />
  <Route path="/teams/new" element={<NewTeams />} />
  <Route path="*" element={<PageError />} />
</Routes>
<Switch>
  <Route path="/teams/:id" component={Teams} />
  <Route path="/teams/new" component={NewTeams} />
</Switch>

V6的Route组件不在要求我们按一定的顺序来定义路由,在旧版本中,当多个路由匹配一个模糊的url时,我们必须以某种方式对路由进行排序,v6版本则会替我们选择最具体的匹配。/teams/new将匹配这两个路由,但只会渲染NewTeams组件。

支持的格式:

  • /groups
  • /groups/admin
  • /users/:id
  • /users/:id/messages
  • /files/*
  • /files/:id/*

嵌套路由

react-router V6支持路由的嵌套,允许父路由控制子路由的渲染,

提供了一个渲染出口组件 Outlet,当匹配到子路由的时候会渲染在Outlet组件所在的位置,父路由此时仍然存在。

支持多级嵌套

const src = () => {
  return (
    <>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/list" element={<List />}>
          <Route path="Detail/:id" element={<Detail />} />
        </Route>
      </Routes>
    </>
  )
}

const List = () => {
  const navigate = useNavigate();
  return (
    <>
      <div className="list">
        <Button
          onClick={() => {
            navigate('/list/detail/1');
          }}
        >
          detail1
        </Button>
        <Button
          onClick={() => {
            navigate('/list/detail/2');
          }}
        >
          detail2
        </Button>
        // react-router提供了Outlet组件用来占位置
        <Outlet />
      </div>
    </>
  );

查询参数

/mysql?mysql_group_id=mysql-test&mysql_instance_id=mysql-asfasfew

react-router V6提供了useSearchParams Hook,它是基于浏览器内置的 URLSearchParams 构造函数进行的封装。

useSearchParams类似useState,返回一个数组,第一个元素是一个Map,可以通过其get方法获取查询字符串中的值,第二个元素是一个函数,用来更新url中的查询字符串。

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

const [searchParams, setSearchParams] = useSearchParams();

const groupId = searchParams.get('mysql_group_id')
const instanceId = searchParams.get('mysql_instance_id')

const updateOrder = (sort) => {
  setSearchParams({ key: value })
}

编程式配置路由

react-router V6还提供了 useRoutes Hook,使我们可以通过写一个配置对象的方式来配置路由,不需要在自行拼接jsx.

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u9plstJr-1665650846994)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a9c3dd7664664973b0661b29800bb814~tplv-k3u1fbpfcp-zoom-1.image)]

const routerConfig = [
  {
    path: "/",
    key: "home",
    label: "common.nav.menu.home",
    icon: <HomeOutlined />,
    element: <Home />,
  },
  {
    key: "authManageWrapper",
    label: "common.nav.menu.authManage",
    icon: <SolutionOutlined />,
    children: [
      {
        path: "/auth/list",
        key: "authList",
        label: "common.nav.menu.authList",
        element: <AuthList />,
      },
      {
        path: "/auth/add",
        key: "addAuth",
        label: "common.nav.menu.addAuth",
        element: <AddAuth />,
      },
    ],
  },
  {
    path: "*",
    hideInMenu: true,
    key: "null",
    element: <Navigate to="/" />,
  },
]
return (
  <>
    {useRoutes(routerConfig)}  
  </>
)

在antd的4.20版本+中,他的Menu导航组件也支持这种写法,可以维护一份routerConfig,对其扩充一些属性,就能同时再Menu组件中使用。

其他

  • 新增useNavigate Hook 代替useHistory Hook
let navigate = useNavigate();
<button
  onClick={() => {
    navigate("/invoices" + location.search);
  }}
>
  jump
</button>
  • 可以在各个地方渲染多组路由:经常有一些需求让我们在某个state为true时展示组件A,为false时展示组件B,这个时候可以尝试在组件内写一个嵌套路由。

总结:

  • 定义路由时 Routes组件和Route组件搭配使用,且可以在不同地方定义多组。Route组件的属性也发生了变更。
  • 新增了Outlet组件,支持路由的嵌套,使用起来可以更加的灵活。
  • 新增了一个可以查询和更新url参数的hook useSearchParams。
  • 提供了 useRoutes Hook, 支持使用js对象的形式来定义路由。

http://www.niftyadmin.cn/n/1784885.html

相关文章

uva 103 - Stacking Boxes

http://uva.onlinejudge.org/index.php?optioncom_onlinejudge&Itemid8&category114&pageshow_problem&problem39 题目读了好久总算看懂了&#xff0c;具有n维属性的箱子a和b&#xff0c;如果a fits b 仅当存在a的属性排列&#xff0c;使与b对应 的属性满足q(…

健康指南

最近&#xff0c;工作压力大&#xff0c;放在工作上的时间越来越多&#xff0c;每天休息的时间只有5个小时左右&#xff0c;造成了精神和身体状况严重不好&#xff0c;倍感抑郁起来&#xff01;不少朋友也有些状况&#xff0c;说来也是唉声一片的&#xff0c;工作和生活如何兼顾…

100款最佳安全工具(世界排行榜)

1、Nessus &#xff1a;最好的UNIX漏洞扫描工具2、Wireshark &#xff1a;嗅探网络粘合胶水&#xff08;网络协议&#xff09;3、Snort &#xff1a;一款广受欢迎的开源IDS&#xff08;Intrusion Detection System&#xff09;&#xff08;***检测系统&#xff09;工具4、Netca…

ahooks中的核心hook-useRequest(下)

前言 之前大致说了下useRequest hook的基本功能的实现。但useRequest的强大不止于此。它还支持如loading状态延时、请求防抖、节流、依赖刷新等功能。不过其实现方式都是通过内置的插件hook来进行实现的。这样做既可以保证核心代码的简洁&#xff0c;还能更方便的扩展出更高级…

Atlas学习手记(22):使用行为增强用户界面(二):Floating Behavior

前面在AtlasControlToolkit中说过&#xff0c;DragPanel封装了Sys.UI.FloatingBehavior&#xff0c;我们已经知道了如何使用服务器端的Extender来实现拖动效果&#xff0c;本文介绍一下直接使用FloatingBehavior来实现Drag&Drop效果。主要内容1&#xff0e;Floating Behavi…

react函数组件如何获取上一轮的props和state? 我用hooks这样来获取

hooks中通过useRef和useEffect获取上一轮的props和state 看一下官方文档对useRef的描述 useRef 当ref对象内容发生变化时,是不会引发组件重新渲染的; 再看一下useEffect的执行实际 他会在浏览器完成布局与绘制之后,在一个延迟时间中被调用. 结合useRef和useEffect,我们就能…

XD教程笔记

一、快捷键 选择&#xff1a; V 粘贴外观&#xff1a; ctrl alt V 矩形&#xff1a; R 组件&#xff1a; ctrl K 椭圆&#xff1a; E 向某一方向对齐&#xff1a; ctrl shift 方向键 钢笔&#xff1a; P 100%显示&#xff1a; ctrl 1 文本&#xff1a; T 锁定&a…

收藏 input按钮onclick大全

<INPUT οnclickdocument.all.WebBrowser.ExecWB(1,1) typebutton value打开 nameButton1> <INPUT οnclickdocument.all.WebBrowser.ExecWB(4,1) typebutton value另存为 nameButton2> <INPUT οnclickdocument.all.WebBrowser.ExecWB(10,1) typeb…