React Router V6 新特性简单解读

1,205 阅读4分钟

React Router 是基于React之上的强大路由库,它可以让你向应用中快速地添加视图和数据流,同时保持页面与URL间的同步

React Router V6 不是更新好一阵子了吗?本就作为一个刚刚学习不久的前端小白,才刚刚搞懂了 React Router V5 的语法特性,没想到过了几天, v6 正式版直接上线了,一开始难以接受的我还是使用 v5 的版本,每一次安装的时候,都要安装指定版本,很是难受,但是听了一节简单讲述 v6 的课,发现v6 真香,然后就花了一天的时间了解了更新的内容,编写了相关的内容,供大家参考。

React Router V6

  • [官网](React Router | Docs Home)

  • <Switch> 重命名为 <Routes>

  • <Route> 的新特性变更

  • 嵌套路由变得更简单

  • useNavigate 代替 useHistory

  • Navigate 代替 Redirect

  • 新钩子 useRoutes 代替 react-router-config

  • 大小减少:从 20kb8kb

<Switch> 重命名为 <Routes>

<Switch> 标签,保证在路径相同的情况下,只匹配第一个,这个可以避免重复匹配;

这里就是单纯的改了一下名字,功能都没有发生改变

// v5
<Routes>
  <Route path="/" component={Home}></Route>
  <Route path="/list" component={List}></Route>
</Routes>

// v5=6
<Switch>
  <Route exact path="/" element={<Home />}></Route>
  <Route path="/list" element={<List />}></Route>
</Switch>

<Route> 的新特性变更

component/renderelement 代替了

优化:在 v5 版本里面,想要给组件传参数是不太直观的,需要利用 RenderProps 的方式透传 routeProps, 而在 v6 版本中,render 与 component 方案合并成了 element 方案,可以轻松传递 props 且不需要透传 roteProps 参数。

// v6 
<Route path=":Listid" element={<List />} /> 
<Route path=":Listid" element={<List animate={true} />} />

// v5 
<Route path=":Listid" component={List} /> 
<Route 
    path=":userId" 
    render={routeProps => ( 
        <Profile routeProps={routeProps} animate={true} /> 
     )} /> 

嵌套路由变得更简单

  • <Route children> 更改为接受子路由
    • 可以直接在 <Route> 在嵌套多个 <Route>
  • <Route path="" > 路径可以支持相对的路径,更加的清晰
  • 新的 API <Outlet>
    • Outlet不需要任何道具,也不会将任何东西传递给它所呈现的内容。它只是组件的子路由的输出。将它们传递给管线渲染的组件,该管线渲染到插座中。

下面就是简单的路由嵌套

<Route path="/user/*" element={<User />} >
   <Route path="list" element={<UserList />} />
   <Route path="add" element={<UserAdd /> } />
   <Route path="detail/:id" element={<UserList />} />
</Route>

// User.jsx 文件 
function User() {
    return (
        < div >
            <ul>
                <li><Link to="/user/add">添加用户</Link></li>
                <li><Link to="/user/list">用户列表</Link></li>
                <li><Link to="/user/detail/100">用户详情</Link></li>
            </ul>
            // 根据不同的路由参数,渲染相关的组件
            <Outlet />
        </div >
    );
}

useNavigate 代替 useHistory

这里就是直接将useHistory 替换成 useNavigate ,然后将里面的 跳转方式进行了转变,由 history.push('/home') ---> navigate('/home');

// v5 
import { useHistory } from 'react-router-dom'; 
function ButtonToHome() { 
    let history = useHistory(); 
    function jumpClick() { 
        history.push('/home'); 
    }; 
    return <button onClick={jumpClick}>Submit</button>; 
};

// v6
import { useNavigate } from 'react-router-dom'; 
function ButtonToHome() { 
    let navigate = useNavigate(); 
    function jumpClick() { 
        navigate('/home'); 
    }; 
    return <button onClick={jumpClick}>Submit</button>; 
};

Navigate 代替 Redirect

就是直接将 路由重定向的 Redirect 换成 Navigate,更符合更新之后的语义化跳转。

// v5
<Route path="*" component={<Redirect to="/" />} />
// 也可以使用 下面的这个进行跳转,但是要注意在<Switch>标签中放到最下面
<Redirect from="/*" to="/" />

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

新钩子 useRoutes 代替 react-router-config

这里进行的路由配置就是和以前的一样,但是将更改的特性都用上来了,这里我还编写了一个 路由懒加载的简单实例。

简单的介绍一下,懒加载涉及的知识点

通过 import()React.lazy 和 Suspense 共同一起实现了 React 的懒加载,也就是我们常说了运行时动态加载。

  • import() 函数是一种动态加载模块的规范实现,其返回是一个 promise这里面。
  • React.lazy 这里才会真正异步执行 import(url)操作,由于并未等待,随后会检查模块是否 Resolved,如果已经Resolved了(已经加载完毕)则直接返回moduleObject.default(动态加载的模块的默认导出),否则将通过 throw 将 thenable 抛出到上层。
  • Suspense 其中就包含了如何处理捕获的异常。就是,React 捕获到异常之后,会判断异常是不是一个 thenable,如果是则会找到 SuspenseComponent ,如果 thenable 处于 pending 状态,则会将其 children 都渲染成 fallback 的值,一旦 thenable 被 resolve 则 SuspenseComponent 的子组件会重新渲染一次。

想要了解# React Lazy 的实现原理可以点这个链接 thoamsy.github.io/blogs/react…

// 路由来加载 lazy()
let LazyProfile = React.lazy(() => import('./Profile'));
const routes = [
    { path: '/', element: <Home /> },
    {
        path: '/profile', element: (
            // 要记得用 Suspense 
            <React.Suspense fallback={<div>loading....</div>}>
                <LazyProfile />
            </React.Suspense>
        )
    },
    {
        path: '/user',
        element: <User />,
        // 这里就是 route 嵌套的编写
        children: [
            { path: 'add', element: <UserAdd /> },
            { path: 'list', element: <UserList /> },
            { path: 'detail/:id', element: <UserDetail /> },
        ]
    },
    { path: '*', element: <Navigate to="/" /> }
]

大小减少:从 20kb8kb

找到一张相关的图片,可以清晰的看出里面的改变,但是我对它里面对代码量的减少不是很了解,就当作是一个知识点记忆。

image.png

总结

React Router v6 的更新个人感觉就是对一些标签的语义化进一步的加强,让路由的使用更加的简单,尤其是子路由支持嵌套,让整体路由排版更加的清晰,还有 Outlet 的提出将 Link 和 Route 写在不同的模块里面,让项目的模块化更加的完善,最后还减少了库的大小,让代码的运行速度相对提高。

总体而言:个人感觉这波更新还是很好的,让编写路由更加的舒畅。最后也希望阅读到这里的你们能够吸收到相关的知识点,了解 React Router v6 的简单使用使用。让我们一起拥抱潮流。