React-router升到v6了?

前言

之前一直负责老项目的迭代,而且很少关注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对象的形式来定义路由。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值