React-Router v6 新特性解读及迁移指南

前言

18 年初, React Router
的主要开发人员创建一个名为 Reach Router
的轻量级替代方案。

原来是相互抗衡的,却没想 React Router
直接拿来合并(真香!)

目前 v6
已是测试最后一版,估计新的特性不出意外就是下面这些了:


  1. 重命名为

  2. 的新特性变更。
  3. 嵌套路由变得更简单。
  4. useNavigate
    代替 useHistory
  5. 新钩子 useRoutes
    代替 react-router-config
  6. 大小减少:从 20kb
    8kb


1.
重命名为

该顶级组件将被重命名。但是,其功能大部分保持不变(嗨,瞎折腾)。

// v5



    

    




// v6 <Route path="/" element={} /> <Route path="profile/*" element={} />


2.
的新特性变更

component/render
element
替代
总而言之,简而言之。就是变得更好用了。

import Profile from './Profile';


// v5 <Route path=":userId" render={routeProps => ( )} />
// v6 <Route path=":userId" element={} /> <Route path=":userId" element={} />

3. 嵌套路由变得更简单

具体变化有以下:


  • 已更改为接受子路由。


  • 更简单的匹配规则。

  • 路径层次更清晰。

3.1 简化嵌套路由定义

v5
中的嵌套路由必须非常明确定义,且要求在这些组件中包含许多字符串匹配逻辑(活久见啊,终于意识到这个问题了。)

且看之前的处理:

// v5

import {

  BrowserRouter,

  Switch,

  Route,

  Link,

  useRouteMatch

} from 'react-router-dom';


function App() { return ( ); }
function Profile() { let { path, url } = useRouteMatch();
return (

); }

而在 v6
中,你可以删除字符串匹配逻辑。不需要任何 useRouteMatch()

// v6

import {

  BrowserRouter,

  Routes,

  Route,

  Link,

  Outlet

} from 'react-router-dom';


function App() { return ( <Route path="/" element={} /> <Route path="profile/*" element={} /> ); }
function Profile() { return (

<Route path="me" element={} /> <Route path=":id" element={} />
); }

当然,还有更酸爽的操作,直接在路由里定义

,然后用接下来的一个新 API
Outlet


3.2 新 API
: Outlet

这玩意儿,像极了 {this.props.children}
,具体用法看以下例子:

function App() {

  return (

    

      

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

        <Route path="profile" element={}>

          <Route path=":id" element={} />

          <Route path="me" element={} />

        

      

    

  );

}


function Profile() { return (
{/* 将直接根据上面定义的不同路由参数,渲染或 */}
) }


3.3 多个

以前,我们只能 在 React App
中使用一个 Routes
。但是现在我们可以在 React App
中使用多个路由,这将帮助我们基于不同的路由管理多个应用程序逻辑。

import React from 'react';

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


function Dashboard() { return (

Look, more routes!

<Route path="/" element={} /> <Route path="invoices" element={} />
); }
function App() { return ( <Route path="/" element={} /> <Route path="dashboard/*" element={} /> ); }


4. 用 useNavigate
代替 useHistory

从一目了然改到双目失明。。。

总感觉 React Router
团队有点儿戏。。。

// v5

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


function MyButton() { let history = useHistory(); function handleClick() { history.push('/home'); }; return ; };

现在, history.push()
将替换为 navigation()

// v6

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


function MyButton() { let navigate = useNavigate(); function handleClick() { navigate('/home'); }; return ; };

history
的用法也将被替换成:

// v5

history.push('/home');

history.replace('/home');


// v6 navigate('/home'); navigate('/home', {replace: true});

强行达成共识


5. 新钩子 useRoutes
代替 react-router-config

感觉又是一波强行 hooks
,但还是相对于之前简洁了一些。。。

function App() {

  let element = useRoutes([

    { path: '/', element:  },

    { path: 'dashboard', element:  },

    { path: 'invoices',

      element: ,

      children: [

        { path: ':id', element:  },

        { path: 'sent', element:  }

      ]

    },

    // 重定向

    { path: 'home', redirectTo: '/' },

    // 404找不到

    { path: '*', element:  }

  ]);

  return element;

}


6. 大小减少:从 20kb
8kb

React Router v6
给我们带来方便的同时,还把包减少了一半以上的体积。。。

感觉可以去看一波源码了。。。

关于奇舞周刊

《奇舞周刊》是360公司大前端团队「 奇舞团
」运营的前端技术社区。关注公众号后,直接发送链接到后台即可给我们投稿。