React-Router V6 使用详解

React-Router V6 使用详解

  • Remix 团队在2020年6月发布了第一个V6.0.0-beta.0版本的React-Router,也预示着V6版本的正式开始,相比V5版本的确有很多方面的升级。
  • 本文将结合V6特性和V5如何升级V6两方面来为大家详细讲解React-Router的使用。
  • (使用版本:V6.0.2稳定版)

一、基本用法

React-Router的安装方法:

npm:npm install react-router-dom

yarnyarn add react-router-dom

  • 目前官方从5开始已经放弃原有的react-router库,统一命名为react-router-dom
使用方法
  • React-Router本身在React开发中就是一个组件,因此在使用时基本遵循组件开发相关原则。这里采用create-react-app来创建一个基础的demo工程演示使用过程。
  1. 创建demo create-react-app my-first-react

安装react-router组件

  1. 启用全局路由模式

全局路由有常用两种路由模式可选:HashRouter 和 BrowserRouter
HashRouter:URL中采用的是hash(#)部分去创建路由,类似www.example.com/#/ BrowserRouter:URL采用真实的URL资源
后续有文章会详细讲HashRouter的原理和实现,这里我们采用BrowserRouter来创建路由

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';

ReactDOM.render(
 <React.StrictMode>
   <BrowserRouter>
     <App />
   </BrowserRouter>
 </React.StrictMode>,
 document.getElementById('root')
);

reportWebVitals();

这样我们在yarn start 或者 npm run start的时候访问/就可以访问这个组件了,具体效果大家可以自行运行

  1. 路由功能
    React-Router V6版本常用路由组件和hooks,其他不常用的大家可以看下官网的介绍
组件名作用说明
<Routers>一组路由代替原有<Switch>,所有子路由都用基础的Router children来表示
<Router>基础路由Router是可以嵌套的,解决原有V5中严格模式,后面与V5区别会详细介绍
<Link>导航组件在实际页面中跳转使用
<Outlet/>自适应渲染组件根据实际路由url自动选择组件
hooks名作用说明
useParams返回当前参数根据路径读取参数
useNavigate返回当前路由代替原有V5中的 useHistory
useOutlet返回根据路由生成的element
useLocation返回当前的location 对象
useRoutes同Routers组件一样,只不过是在js中使用
useSearchParams用来匹配URL中?后面的搜索参数

App.js

  • 这里创建了两个组件Home和About,然后分别注册/和about,在每个页面还有Link来进行导航

    import './App.css';
    import { Routes, Route, Link } from "react-router-dom"
    function App() {
     return (
       <div className="App">
         <header className="App-header">
           <Routes>
             <Route path="/" element={<Home />}></Route>
             <Route path="/about" element={<About />}></Route>
           </Routes>
         </header>
       </div>
     );
    }
    function Home() {
     return <div>
       <main>
         <h2>Welcome to the homepage</h2>
       </main>
       <nav>
         <Link to="/about">about</Link>
       </nav>
     </div>
    }
    function About() {
     return <div>
       <main>
         <h2>Welcome to the about page</h2>
       </main>
       <nav>
         <ol>
           <Link to="/">home</Link>
           <Link to="/about">about</Link>
         </ol>
    
       </nav>
     </div>
    }
    export default App;
    

    运行后 imagepng

    imagepng

    至此,一个最简单的路由demo就正常运行了。

  1. 嵌套路由

嵌套路由是V6版本对之前版本一个较大的升级,采用嵌套路由会智能的识别

function App() {
 return (
   <Routes>
     <Route path="user" element={<Users />}>        
         <Route path=":id" element={<UserDetail />} />        
         <Route path="create" element={<NewUser />} />      
     </Route>
   </Routes>
 );
}

当访问 /user/123 的时候,组件树将会变成这样

<App>
   <Users>
       <UserDetail/>
   </Users>
</App>

当访问/user/create的时候,组件树将变成这样

<App>
  <Users>
      <NewUser/>
  </Users>
</App>

如果只是内部组件修改,也可以采用<Outlet/>来直接实现,如下所示

function App() {
 return (
   <Routes>
     <Route path="user" element={<Users />}>        
         <Route path=":id" element={<UserDetail />} />        
         <Route path="create" element={<NewUser />} />      
     </Route>
   </Routes>
 );
}

function Users() {
 return (
   <div>
     <h1>Users</h1>
     <Outlet />
   </div>
 );
}
  1. index路由

方式1:index属性解决当嵌套路由有多个子路由但本身无法确认默认渲染哪个子路由的时候,可以增加index属性来指定默认路由,或者使用使用useNavigate

import React, { useEffect } from 'react'
import { Routes, Route, useNavigate } from 'react-router-dom'
import Layout from '@/layout/Index'
import NotFound from '@/pages/NotFound'
import Login from '@/pages/Login'
import Home from '@/pages/Home'

// 跳转路由
const Redirect: React.FC<{ to: string }> = props => {
  const navigate = useNavigate()
  useEffect(() => {
    navigate(props.to)
  })
  return null
}

const App: React.FC = () => {
  // 默认跳转/home
  // return (
  //   <div>
  //     <Routes>
  //       <Route path="/" element={<Layout />}>
  //         {/* 方式1 添加index属性 把它自己的path去掉 */}
  //         <Route index element={<Home />} />
  //       </Route>
  //       <Route path="/Login" element={<Login />} />
  //       <Route path="*" element={<NotFound />} />
  //     </Routes>
  //   </div>
  // )

  return (
    <div>
      <Routes>
        {/* 方式2: */}
        <Route path="/" element={<Redirect to="/home" />} />
        <Route path="/" element={<Layout />}>
          <Route path="/home" element={<Home />} />
        </Route>
        <Route path="/Login" element={<Login />} />
        <Route path="*" element={<NotFound />} />
      </Routes>
    </div>
  )
}

export default App

这样当访问/的时候<Outlet/>会默认渲染About组件

  1. 路由通配符
  • 整个react-router支持以下几种通配符
/groups
/groups/admin
/users/:id
/users/:id/messages
/files/*
/files/:id/*
123456

注意,以下这些正则方式在V6里面是不支持的

/users/:id?
/tweets/:id(\d+)
/files/*/cat.jpg
/files-*
1234

这里的*只能用在/后面,不能用在实际路径中间

关于NotFound类路由,可以用*来代替

function App() {
 return (
   <Routes>
     <Route path="/" element={<Home />} />      
     <Route path="dashboard" element={<Dashboard />} />      
     <Route path="*" element={<NotFound />} />    
   </Routes>
 );
}
123456789
  1. 获取参数 useParams 和useSearchParams

假设现有App路由

function App() {
    return (
      <Routes>
        <Route path="user" element={<Users />}>       
  	      <Route path=":id" element={<UserDetail />} />       
  	      <Route path="create" element={<NewUser />} />     
        </Route>
      </Routes>
    );
}
12345678910

那么在UserDetail内部需要用useParams来获取对应的参数

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

export default function UserDetail() {
 let params = useParams();
 return <h2>User: {params.id}</h2>;
}
123456

useSearchParams相对复杂,他返回的是一个当前值和set方法

let [searchParams, setSearchParams] = useSearchParams();

使用时可以用searchParams.get("id")来获取参数,同时页面内也可以setSearchParams({“id”:2})来改变路由,这样当访问 http://URL/user?id=111 时就可以获取和设置路径

  1. useNavigate

useNavigate是替代原有V5中的useHistory的新hooks,其用法和useHistory类似,整体使用起来更轻量,他的声明方式如下:

declare function useNavigate(): NavigateFunction;

interface NavigateFunction {
 (
   to: To,
   options?: { replace?: boolean; state?: State }
 ): void;
 (delta: number): void;
}
123456789
 //js写法
 let navigate = useNavigate();
 function handleClick() {
   navigate("/home");
 }
 //组件写法
 function App() {
    return <Navigate to="/home" replace state={state} />;
 }
 //替代原有的go goBack和goForward
<button onClick={() => navigate(-2)}>
   Go 2 pages back
 </button>
 <button onClick={() => navigate(-1)}>Go back</button>
 <button onClick={() => navigate(1)}>    Go forward  </button>
 <button onClick={() => navigate(2)}>    Go 2 pages forward  </button>
12345678910111213141516

二、与V5的区别

1.用<Routes> children形式替代<Switch>

V5写法:

 function App() {
   return (
     <Switch>
       <Route exact path="/">
         <Home />
       </Route>
       <Route path="/about">
         <About />
       </Route>
       <Route path="/users/:id" children={<User />} />     
     </Switch>
   );
 }

V6写法

 function App() {
   return (
     <Routes>
       <Route index path="/" element={<Home />} />      
	       <Route path="about" element={<About />} />       
	       <Route path="/users/:id" element={<User />} />     
       </Routes>
   );
 }
2.去除Switch中的<Redirect>,用react-router-dom中的Redirect 替代,或者用 <Navigate> 实现

V5写法:

 <Switch>
   <Redirect from="about" to="about-us" />
 </Switch>

V6写法:

 <Route path="about" render={() => <Redirect to="about-us" />}
3.<Link to>支持相对位置

V5版本的to属性只支持绝对位置,如<Lint to="me">表示<Lint to="/me">,如果当时正在Users组件内,想跳转需要<Lint to="/users/me">。在V6中,Link默认支持相对位置,也就是<Lint to="me"> 在Users组件内会等价于<Lint to="/users/me">,同时支持’…’ 和’.'等相对路径写法。

// If your routes look like this
<Route path="app">
<Route path="dashboard">
 <Route path="stats" />
</Route>
</Route>

// and the current URL is /app/dashboard (with or without
// a trailing slash)
<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">
4.使用useNavigate代替useHistory

可以参考上面useNavigate使用,这里不再赘述


三、路由配置,嵌套路由

React Router 提供了两个接口来配置路由

  • :通过在jsx中组件方式

  • useRouters通过对象配置方式

例:在index.js里通过配置

import React from 'react';
import ReactDOM from 'react-dom';
import { store } from './app/store';
import { Provider } from 'react-redux';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './App';
import { PostsList  } from './features/posts/PostsList';
import { SinglePostPage } from './features/posts/SinglePostPage';
import * as serviceWorker from './serviceWorker';
import './index.css';
 
ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <Routes>
          <Route path='/' element={<App />} />
           {/* 嵌套路由 */}
          <Route path="/postList" element={<PostsList />}>
            <Route index element={<div>我是index默认子路由</div>} />
            <Route path=":id" element={<div>我是子路由元素</div>} />
          </Route>
          <Route path="/singlePostPage/:postId" element={<SinglePostPage />} />
          <Route path="*" element={<App />} />
        </Routes>
      </BrowserRouter>
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);
serviceWorker.unregister();

例:在index.js里通过useRouters配置,此处配置可提出至单独文件

import React from 'react';
import ReactDOM from 'react-dom';
import { store } from './app/store';
import { Provider } from 'react-redux';
import { BrowserRouter, useRoutes } from 'react-router-dom';
import App from './App';
import { PostsList  } from './features/posts/PostsList';
import { SinglePostPage } from './features/posts/SinglePostPage';
import './index.css';
 
const GetRoutes = () => {
  const routes = useRoutes([
    { path: '/', element: <App /> },
    { 
      path: '/postList',
      element: <PostsList />,
      children: [
        { path: '/postList/:id', element: <div>我是子路由元素</div> },
        { path: '*', element: <div>404</div>}
      ],
    },
    { path: '/singlePostPage/:postId', element: <SinglePostPage /> },
    { path: '*', element: <div>404</div>}
  ])
  return routes;
}
ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <GetRoutes />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
);

注意嵌套路由需要在父路由使用Outlet呈现其子路由元素

import React from 'react';
import { useSelector } from 'react-redux';
import { Link, Outlet } from 'react-router-dom'
 
export const PostsList = () => {
  const posts = useSelector(state => state.posts);
  const renderedPosts = posts.map(post => (
    <div key={post.id}>
      <h3>{post.title}</h3>
      <p>{post.content.substring(0,100)}</p>
      <Link to={`/singlePostPage/${post.id}`}> 查看详情</Link>
    </div>
  ))
  return (
    <section>
      <h2>posts</h2>
      {renderedPosts}
      {/* 子路由渲染位置 */}
      <Outlet />
    </section>
  )
}

四、总结

V6版本的react-router升级了原有嵌套路由写法,并且重新实现了useNavigate来替代useHistory,整体上更加好理解。当然还有些其他属性和方法没有再介绍,大家如果有其他想知道的也可以回复我来补充。

参考链接:

React-Router V6 使用详解 原文链接:https://blog.csdn.net/weixin_44733660/article/details/123204029

React Router v6 路由配置,嵌套路由 原文链接:https://blog.csdn.net/Snow_GX/article/details/123656412

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React Router DOM v6 是一个用于 React 应用程序的路由库。它提供了一种在应用程序中进行页面导航和管理的方式。 下面是一个简单的使用教程来帮助你开始使用 React Router DOM v6: 1. 安装 React Router DOM v6: ```shell npm install react-router-dom@next ``` 注意:v6 目前仍然是预发布版本,所以需要添加 `@next` 后缀来安装最新版本。 2. 在你的应用程序的入口文件(通常是 `index.js`)中导入所需的组件: ```jsx import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; ``` 3. 使用 `Router` 组件将你的应用程序包裹起来,并定义你的路由规则: ```jsx ReactDOM.render( <Router> <Route path="/" component={App} /> </Router>, document.getElementById('root') ); ``` 这个例子中,所有匹配 `/` 路径的组件都将渲染 `App` 组件。 4. 在你的应用程序的其他组件中使用 `Link` 组件来创建导航链接: ```jsx import { Link } from 'react-router-dom'; function Navigation() { return ( <nav> <ul> <li> <Link to="/">Home</Link> </li> <li> <Link to="/about">About</Link> </li> <li> <Link to="/contact">Contact</Link> </li> </ul> </nav> ); } ``` 这个例子中,点击链接将会导航到对应的路径。 5. 在你的应用程序的其他组件中使用 `Route` 组件来定义不同路径下的组件渲染: ```jsx import { Route } from 'react-router-dom'; function App() { return ( <div> <h1>My App</h1> <Route exact path="/" component={HomePage} /> <Route path="/about" component={AboutPage} /> <Route path="/contact" component={ContactPage} /> </div> ); } ``` 这个例子中,`HomePage` 组件将会在 `/` 路径下渲染,`AboutPage` 组件将会在 `/about` 路径下渲染,`ContactPage` 组件将会在 `/contact` 路径下渲染。 这只是 React Router DOM v6 的一些基本用法,还有很多其他功能和概念可以学习。你可以查阅官方文档以获取更多详细的信息和示例代码:https://reactrouter.com/docs/en/v6

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值