【第九章-React Router 6】
- 一、概述
- 二、一级路由
-
- [1. 准备工作](#1. 准备工作)
- [2. 安装](#2. 安装)
- [3. 配置路由](#3. 配置路由)
-
- [3.1 引入BrowserRouter包裹整个路由器](#3.1 引入BrowserRouter包裹整个路由器)
- [3.2 编写路由链接和注册路由](#3.2 编写路由链接和注册路由)
- [3.3. 核心变化总结](#3.3. 核心变化总结)
- 三、重定向
-
- [1. Navigate组件的使用](#1. Navigate组件的使用)
- [2. Navigate组件的案例](#2. Navigate组件的案例)
- [3. replace 模式](#3. replace 模式)
- [四、NavLink 高亮](#四、NavLink 高亮)
-
- [1. 基本使用与默认高亮](#1. 基本使用与默认高亮)
- [2. 自定义类名(使用函数)](#2. 自定义类名(使用函数))
- [五、 useRoutes 路由表](#五、 useRoutes 路由表)
-
- [1. 核心概念](#1. 核心概念)
- [2. 使用步骤与代码示例](#2. 使用步骤与代码示例)
- 六、嵌套路由
-
- [1. 准备工作](#1. 准备工作)
- [2. 配置二级路由](#2. 配置二级路由)
- [3. 子路由路径的三种写法](#3. 子路由路径的三种写法)
- [4. end属性](#4. end属性)
- [七. 路由的传参方式](#七. 路由的传参方式)
-
- [1. 准备工作](#1. 准备工作)
-
- [1.1 优化Message组件](#1.1 优化Message组件)
- [1.2 配置三级路由](#1.2 配置三级路由)
- [2. 通过 params 参数传参](#2. 通过 params 参数传参)
- [3. 通过 search 参数传参](#3. 通过 search 参数传参)
- [4. 通过 state 参数传参](#4. 通过 state 参数传参)
- 八、编程式路由导航
-
- [1. Navigate 组件与 useNavigate 钩子的区别](#1. Navigate 组件与 useNavigate 钩子的区别)
- [2. 基本用法](#2. 基本用法)
- [3. Navigate的其他传参方式](#3. Navigate的其他传参方式)
- [4. 使用 Navigate 实现前进和后退](#4. 使用 Navigate 实现前进和后退)
- 九、useInRouterContext
- 十、useNavigationType
- 十一、useOutlet
- 十二、useResolvedPath
一、概述
1.React Router 以三个不同的包发布到 npm 上,它们分别为:
- react-router:路由的核心库,提供了很多的:组件、钩子。
- react-router-domt:包含react-router所有内容,并添加一些专门用于 DOM 的组件,例如
<BrowserRouter>等。 - react-router-native:包括react-router所有内容,并添加一些专门用于ReactNative的AP!,例如
<NativeRouter>等。
2.与 React Router 5.x 版本相比,改变了什么?
- 内置组件的变化:移除
<switch/>,新增<Routes/>等。 - 语法的变化:
component={About}变为element={<About/>}等。 - 新增多个hook:
useParams、useNavigate、useMatch等。 - 官方明确推荐函数式组件了!!!
二、一级路由
1. 准备工作
我们还是继续使用之前讲解 React Router5 的代码为例。
App.jsx
javascript
import Home from './pages/Home'
import About from './pages/About'
import './App.css';
function App() {
return (
<div classNameName="App">
<div className="container mt-4" style={{maxWidth: '1000px'}}>
<div className="row">
<div className="col">
<h1 className="header-title text-dark">React Router Demo</h1>
<span className="text-muted"></span>
</div>
</div>
<div className="row mt-4">
<div className="col-3">
<div className="list-group">
<a href="./about.html" class="list-group-item list-group-item-action text-secondary">About</a>
<a href="./home.html" class="list-group-item list-group-item-action active bg-primary border-primary">Home</a>
</div>
</div>
<div className="col-9 content-area">
<Home />
<About />
</div>
</div>
</div>
</div>
);
}
export default App;
pages/About/index.jsx
javascript
import React from 'react'
export default function Home() {
return (
<div>我是About的内容</div>
)
}
pages/Home/index.jsx
javascript
import React from 'react'
export default function About() {
return (
<div>我是About的内容</div>
)
}
2. 安装
javascript
npm install react-router-dom
3. 配置路由
3.1 引入BrowserRouter包裹整个路由器
index.js
javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import {BrowserRouter} from 'react-router-dom';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
3.2 编写路由链接和注册路由
javascript
import { NavLink, Routes, Route } from "react-router-dom";
...
<div className="list-group">
{/* 路由链接 */}
<NavLink to="/about" className="list-group-item list-group-item-action text-secondary">About</NavLink>
<NavLink to="/home" className="list-group-item list-group-item-action text-secondary">Home</NavLink>
</div>
<div className="col-9 content-area">
{/* 注册路由 */}
<Routes>
<Route path="/about" element={<About />} />
<Route path="/home" element={<Home />} />
</Routes>
</div>
3.3. 核心变化总结
<Routes>替代<Switch>:v6 中所有的<Route>必须被<Routes>包裹。element属性替代组件标签:指定渲染内容时使用element = {<Home />},而不是旧版本的component={Home}或子节点。
注意:<Route casesensitive>属性用于指定匹配时是否区分大小写(默认为 false)。
javascript
<Route caseSensitive path="/HOME" element={<Home />} />
若开启大小写匹配模式,则/home无法匹配到/HOME。

三、重定向
1. Navigate组件的使用
在 react-router-dom v6 中,我们使用<Navigate>代替 <Redirect> ,<Navigate> 是一个用于重定向的组件,当它被渲染时,会自动修改当前页面的路径,切换视图。
语法:<Navigate to="/xxx" />
javascript
<Routes>
<Route path="/about" element={<About />} />
<Route path="/home" element={<Home />} />
<Route path="/" element={<Navigate to="/about" />}></Route>
</Routes>

2. Navigate组件的案例
Navigate只要渲染就会引起视图的切换,为了深入理解Navigate,我们来实现一个小案例。
Home 组件添加一个sum值和点击按钮,当sum===2的时候,就自动跳转 About 组件。
src/pages/Home/index.jsx
javascript
import React from 'react'
import { Navigate } from 'react-router-dom'
export default function Home() {
const [sum, setSum] = React.useState(0)
return (
<div>
<div>我是Home的内容</div>
<div>
{
sum === 2 ? <Navigate to="/about" /> : <p>当前sum值是:{sum}</p>
}
<div>
<button onClick={() => setSum(2)}>点我将sum变成2</button>
</div>
</div>
</div>
)
}

点击按钮,切换到About组件:

3. replace 模式
替换历史记录默认是 push 模式:
javascript
<Navigate to="/about" replace={false}/>
如果希望覆盖当前历史记录,可以设置 replace: true
javascript
<Navigate to="/about" replace={true}/>
四、NavLink 高亮
在 react-router-dom v6 中,NavLink 组件默认会自动给当前激活的链接添加一个名为 active 的 CSS 类名,且废弃了 v5 中的 activeClassName 属性。
1. 基本使用与默认高亮
默认情况下,直接使用 NavLink 并编写 .active 样式即可实现高亮:
javascript
<NavLink to="/about" className="list-group-item list-group-item-action text-secondary">About</NavLink>
<NavLink to="/home" className="list-group-item list-group-item-action text-secondary">Home</NavLink>

2. 自定义类名(使用函数)
但有的时候,我们的高亮的类名不一定是active,就需要将 className 属性写成一个回调函数,接收一个参数 { isActive },然后动态判断并返回自定义类名。
比如:我们定义高亮的类名为atguigu。
css
.atguigu {
background-color: orange !important;
color: #007bff !important;
}
然后我们在 className 的回调函数里结构isActive,若isActive为true则代表是当前路由,需要添加类名atguigu。
javascript
<NavLink to="/about" className={({isActive}) => isActive ? "atguigu list-group-item list-group-item-action text-secondary":"list-group-item list-group-item-action text-secondary"}>About</NavLink>
<NavLink to="/home" className={({isActive}) => isActive ? "atguigu list-group-item list-group-item-action text-secondary":"list-group-item list-group-item-action text-secondary"}>Home</NavLink>
感觉这样的写法有点过于冗杂,我们可以把 className 里的逻辑封装成一个函数。
javascript
function App() {
// 是否添加高亮
function computedClassName(isActive) {
return isActive
? "atguigu list-group-item list-group-item-action text-secondary"
: "list-group-item list-group-item-action text-secondary";
}
return (
<div className="App">
<div className="container mt-4" style={{ maxWidth: "1000px" }}>
<div className="row">
<div className="col">
<h1 className="header-title text-dark">React Router Demo</h1>
<span className="text-muted"></span>
</div>
</div>
<div className="row mt-4">
<div className="col-3">
<div className="list-group">
{/* 路由链接 */}
<NavLink
to="/about"
className={({ isActive }) => computedClassName(isActive)}
>
About
</NavLink>
<NavLink
to="/home"
className={({ isActive }) => computedClassName(isActive)}
>
Home
</NavLink>
</div>
</div>
<div className="col-9 content-area">
{/* 注册路由 */}
<Routes>
<Route path="/about" element={<About />} />
<Route path="/home" element={<Home />} />
<Route path="/" element={<Navigate to="/about" />}></Route>
</Routes>
</div>
</div>
</div>
</div>
);
}
这样就可以完成自定义类名的高亮效果了!!!


五、 useRoutes 路由表
在 react-router-dom v6 中,useRoutes 是一个钩子(Hook ),它用 JavaScript 对象(路由表) 代替了 <Routes> 和 <Route> 组件来配置路由。
1. 核心概念
- 作用:以对象形式集中管理路由,使代码更清爽、更易于维护。
- 位置限制 :必须在
<BrowserRouter>或其他路由 Provider 组件内部执行。 - 嵌套渲染 :子路由通过
<Outlet />组件在父组件中渲染。
2. 使用步骤与代码示例
- 第一步:编写路由表文件
定义一个数组,每个对象代表一个路由,使用 path、element 。
src/routes/index.js
javascript
import { Navigate } from "react-router-dom";
import Home from "../pages/Home";
import About from "../pages/About";
// 定义路由规则
const routes = [
{ path: "/about", element: <About /> },
{ path: "/home", element: <Home /> },
{ path: "/", element: <Navigate to="/about" /> },
];
export default routes;
- 第二步:在根组件或 App 中使用 useRoutes
引入路由表数组 ,并传给 useRoutes 钩子生成实际的路由结构,代替<Routes>和<Route>渲染到页面上。
App.jsx
javascript
import { NavLink, useRoutes } from "react-router-dom";
// 1. 引入路由表数组
import routes from "./routes"
function App() {
// 2. 根据路由表生成对应的路由组件
const element = useRoutes(routes);
return (
<div className="App">
<div className="row mt-4">
<div className="col-3">
<div className="list-group">
{/* 路由链接 */}
{...}
</div>
</div>
<div className="col-9 content-area">
{/* 注册路由 */}
{/* 3.渲染匹配到的路由组件 */}
{element}
</div>
</div>
</div>
</div>
);
}
export default App;
六、嵌套路由
1. 准备工作
首先,我们创建两个二级路由页面,分别是 News 和 Message 。
src/pages/Home/News/index.jsx
javascript
export default function News() {
return (
<div
className="tab-pane fade show active"
id="news"
role="tabpanel"
aria-labelledby="news-tab"
>
<ul className="news-list">
<li>news001</li>
<li>news002</li>
<li>news003</li>
</ul>
</div>
);
}
src/pages/Home/Message/index.jsx
javascript
export default function Message() {
return (
<div
className="tab-pane fade show active"
id="message"
role="tabpanel"
aria-labelledby="message-tab"
>
<ul className="news-list">
<li>message001</li>
<li>message002</li>
<li>message003</li>
</ul>
</div>
);
}
src/pages/Home/index.jsx
javascript
import News from "./News";
import Message from "./Message";
export default function Home() {
return (
<div>
<div>我是Home的内容</div>
<div className="custom-card">
<ul className="nav nav-tabs-custom" id="myTab" role="tablist">
<li className="nav-item" role="presentation">
<button
className="nav-link active"
id="news-tab"
data-bs-toggle="tab"
data-bs-target="#news"
type="button"
role="tab"
aria-controls="news"
aria-selected="true"
>
News
</button>
</li>
<li className="nav-item" role="presentation">
<button
className="nav-link"
id="message-tab"
data-bs-toggle="tab"
data-bs-target="#message"
type="button"
role="tab"
aria-controls="message"
aria-selected="false"
>
Message
</button>
</li>
</ul>
<div className="tab-content" id="myTabContent">
<News />
<Message />
</div>
</div>
</div>
);
}
2. 配置二级路由
- 使用路由表制定路由规则。
src/routes/index.js
javascript
import { Navigate } from "react-router-dom";
import Home from "../pages/Home";
import About from "../pages/About";
// 1. 引入两个子路由组件
import News from "../pages/Home/News";
import Message from "../pages/Home/Message";
const routes = [
{
path: "/about",
element: <About />
}, {
path: "/home",
element: <Home />,
// 2. 子路由配置,path直接写子路由的路径名字即可
children: [
{
path: "news",
element: <News />
},
{
path: "message",
element: <Message />
},
]
}, {
path: "/",
element: <Navigate to="/about" />
},
];
export default routes;
- 使用
NavLink替换导航标签
src/pages/Home/index.jsx
javascript
<ul className="nav nav-tabs-custom" id="myTab" role="tablist">
<li className="nav-item" role="presentation">
<NavLink to="news" className="nav-link">News</NavLink>
</li>
<li className="nav-item" role="presentation">
<NavLink to="message" className="nav-link">Message</NavLink>
</li>
</ul>
- 使用
Outlet占位渲染子路由
在父组件中引入并放置 <Outlet />,子路由的内容会在该位置渲染。
src/pages/Home/index.jsx
javascript
import { NavLink, Outlet } from "react-router-dom";
export default function Home() {
return (
<div>
<div>我是Home的内容</div>
<div className="custom-card">
<ul className="nav nav-tabs-custom" id="myTab" role="tablist">
<li className="nav-item" role="presentation">
<NavLink to="news" className="nav-link">News</NavLink>
</li>
<li className="nav-item" role="presentation">
<NavLink to="message" className="nav-link">Message</NavLink>
</li>
</ul>
<div className="tab-content" id="myTabContent">
{/* 指定路由组件呈现的位置 */}
<Outlet />
</div>
</div>
</div>
);
}
页面效果:


3. 子路由路径的三种写法
- 直接简写
javascript
<NavLink to="news" className="nav-link">News</NavLink>
javascript
{
path: "news",
element: <News />
}
- 带上父组件路径(与V5一样)
javascript
<NavLink to="/home/news" className="nav-link">News</NavLink>
javascript
{
path: "/home/news",
element: <News />
}
- 使用./xxx
javascript
<NavLink to="./news" className="nav-link">News</NavLink>
javascript
{
path: "./news",
element: <News />
}
注意:不管使用哪种写法,都不能直接使用/xxx的写法,不然会从根路径直接跳转。
javascript
<NavLink to="/news" className="nav-link">News</NavLink>

4. end属性
React-router-dom v6 的 end 属性用于 NavLink 组件,用来控制当子路由被激活时,父路由链接是否仍然保持高亮状态。
我们当前的页面效果,当父子路由同时高亮:

在 App.jsx 中添加end属性:
javascript
<NavLink
to="/home"
end
className="list-group-item list-group-item-action text-secondary"
>
Home
</NavLink>
只有子路由保持高亮了:

七. 路由的传参方式
【需求 】:我们想在 Message 组件下方创建一个 Detail 组件(也就是三级路由组件 ),点击 Message ,携带详情参数跳转到对应的详情页面。
【案例效果】:


1. 准备工作
1.1 优化Message组件
- 首先, Message 组件的每一项内容需要通过动态遍历状态数组来生成。
src/pages/Home/Message/index.jsx
javascript
import React from 'react'
export default function Message() {
const [messages] = React.useState([
{
id: '001',
title: 'message001',
content: '锄禾日当午',
}, {
id: '002',
title: 'message002',
content: '汗滴禾下土',
}, {
id:'003',
title: 'message003',
content: '谁知盘中餐',
}, {
id: '004',
title: 'message004',
content: '粒粒皆辛苦',
},
])
return (
<div
className="tab-pane fade show active"
id="message"
role="tabpanel"
aria-labelledby="message-tab"
>
<ul className="news-list">
{
messages.map(item => {
return (
<li key={item.id}>{item.title}</li>
)
})
}
</ul>
</div>
);
}
- 在 Message 目录下创建 Detail 文件夹,新增 Detail 组件。
src/pages/Home/Message/Detail/index.jsx
javascript
export default function Detail() {
return (
<div>
<p>id:</p>
<p>title:</p>
<p>content:</p>
</div>
);
}
1.2 配置三级路由
- 找到路由表,制定路由规则。
src/routes/index.js
javascript
...
// 1. 引入 Detail 组件
import Detail from "../pages/Home/Message/Detail";
const routes = [
{
path: "/about",
element: <About />
}, {
path: "/home",
element: <Home />,
children: [
{
path: "news",
element: <News />
},
{
path: "message",
element: <Message />,
// 2. 制定路由
children: [
{
path: "detail",
element: <Detail />
}
]
},
]
}, {
path: "/",
element: <Navigate to="/about" />
},
];
export default routes;
- 因为三级路由不需要高亮效果,所以使用
Link替换导航标签。
src/pages/Home/Message/index.jsx
javascript
import { Link } from "react-router-dom";
...
<ul className="news-list">
{messages.map((item) => {
return (
<li key={item.id}>
{/* 路由链接 */}
<Link to="detail">{item.title}</Link>
</li>
);
})}
</ul>
- 使用
Outlet占位渲染子路由。
src/pages/Home/Message/index.jsx
javascript
import React from "react";
import { Link, Outlet } from "react-router-dom";
export default function Message() {
const [messages] = React.useState([
{
id: "001",
title: "message001",
content: "锄禾日当午",
},
{
id: "002",
title: "message002",
content: "汗滴禾下土",
},
{
id: "003",
title: "message003",
content: "谁知盘中餐",
},
{
id: "004",
title: "message004",
content: "粒粒皆辛苦",
},
]);
return (
<div
className="tab-pane fade show active"
id="message"
role="tabpanel"
aria-labelledby="message-tab"
>
<ul className="news-list">
{messages.map((item) => {
return (
<li key={item.id}>
<Link to="detail">{item.title}</Link>
</li>
);
})}
</ul>
<hr />
{/* 指定路由组件的展示位置 */}
<Outlet />
</div>
);
}
路由配置完成,页面效果如下:

2. 通过 params 参数传参
传参一共分为三步:路由表添加参数占位、跳转路由传参、以及参数的接收。
- 配置路由(添加占位符)
在路由路径中使用 : 来指定参数名。
javascript
{
path: "message",
element: <Message />,
children: [
{
path: "detail/:id/:title/:content",
element: <Detail />
}
]
},
- 传递参数(跳转路由)
在组件中把参数直接拼接到 URL 路径中。
javascript
<Link to={`detail/${item.id}/${item.title}/${item.content}`}>{item.title}</Link>
- 接收参数
在目标组件中通常使用 useParams 钩子获取路由传过来的参数对象。
src/pages/Home/Message/Detail/index.jsx
javascript
import { useParams } from "react-router-dom";
export default function Detail() {
const { id, title, content } = useParams();
return (
<div>
<p>id:{id}</p>
<p>title:{title}</p>
<p>content:{content}</p>
</div>
);
}
那么现在参数已经成功的传给了 Detail 组件:

注意:除了使用useParams获取传过来的 params 参数,使用 useMatch也是可以的(通常不会使用,了解即可)。
javascript
import { useMatch } from "react-router-dom";
const matchObj = useMatch('/home/message/detail/:id/:title/content');
3. 通过 search 参数传参
search 路由传参通过在 URL 后拼接 ?key=value 的形式传递数据,并在目标组件中使用 useSearchParams 钩子来获取参数。
- 传递 search 参数
通过组件里的 <Link> 标签传递 search 参数。
javascript
{/* 直接拼接字符串路径 */}
<Link to={`detail?id=${item.id}&title=${item.title}&content=${item.content}`}>{item.title}</Link>
- 接收 search 参数
在目标组件中,导入并使用 useSearchParams 钩子。它的用法类似于 React 的 useState(你要通过一个数组 去接受),它会返回一个包含 search参数 和 更新search参数的函数 的数组。
src/pages/Home/Message/Detail/index.jsx
javascript
import { useSearchParams } from "react-router-dom";
export default function Detail() {
const [search, setSearch] = useSearchParams();
// 获取具体参数值
const id = search.get("id");
const title = search.get("title");
const content = search.get("content");
return (
<div>
<p>id:{id}</p>
<p>title:{title}</p>
<p>content:{content}</p>
</div>
);
}
页面效果:

- setSearch 函数
它主要用于更新你所收到的search参数。
比如:我们在 Detail 组件中添加一个更新按钮,点击可以更新search参数。
javascript
import { useSearchParams } from "react-router-dom";
export default function Detail() {
const [search, setSearch] = useSearchParams();
const id = search.get("id");
const title = search.get("title");
const content = search.get("content");
return (
<div>
<button
onClick={() => setSearch("id=000&title=message000&content=lalaland")}
>
改变search的值
</button>
<p>id:{id}</p>
<p>title:{title}</p>
<p>content:{content}</p>
</div>
);
}
点击前:

点击后:

注意:除了使用useSearchParams获取传过来的 search 参数,使用 useLoaation也是可以的(通常不会使用,了解即可)。
javascript
import { useLocation } from "react-router-dom";
const locationObj = useLocation();

4. 通过 state 参数传参
使用 state 传参是通过路由导航时附加一个隐藏的状态对象,不会在 URL 地址栏中显示,非常适合传递敏感信息或复杂数据。
- 绑定 state 属性传递参数
直接在 <Link> 上绑定 state 属性。
javascript
<li key={item.id}>
<Link
to="detail"
state={{
id: item.id,
title: item.title,
content: item.content,
}}
>
{item.title}
</Link>
</li>
- 接收参数
在目标组件中,使用 useLocation 钩子函数获取 location.state 中的数据。
javascript
import { useLocation } from "react-router-dom";
const loacationObj = useLocation();
获取到的loacationObj如下所示,只要对它解构便可以拿到对应的参数值。

src/pages/Home/Message/Detail/index.jsx
javascript
import { useLocation } from "react-router-dom";
export default function Detail() {
const { state: { id, title, content } } = useLocation();
return (
<div>
<p>id:{id}</p>
<p>title:{title}</p>
<p>content:{content}</p>
</div>
);
}
页面效果:

八、编程式路由导航
React Router v6 使用 useNavigate 钩子(Hook)来实现函数组件中的编程式路由跳转。它替代了旧版本中的 useHistory。
1. Navigate 组件与 useNavigate 钩子的区别
两者都是实现路由跳转的方式,但本质完全不同:
- Navigate 是 React 组件:必须在组件的渲染输出中使用,通过渲染这个组件触发跳转,属于声明式导航。
- useNavigate 是 React 钩子:调用它会返回一个跳转函数,通过主动调用函数触发跳转,属于编程式导航。
2. 基本用法
在函数组件中调用 useNavigate 得到一个导航函数,然后调用它来跳转页面。
javascript
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('xxx')
我们还是继续以上面的 Message 组件为例,我们分别在<Link>后面加上一个【跳转详情 】的按钮,点击该按钮,即可跳转到对应的 Detail组件。

src/pages/Home/Message/index.jsx
javascript
import React from "react";
// 1. 引入 useNavigate
import { Link, Outlet, useNavigate } from "react-router-dom";
export default function Message() {
// 2. 获取navigate函数用于跳转
const navigate = useNavigate();
const [messageState] = React.useState([...]);
// 点击前往详情页面
function toDetailPage(item) {
// 3.实现跳转并传入state参数
navigate('detail', {
// 是否为replace跳转模式,默认为 false,如果为默认值时可以省略
replace: false,
state: {
id: item.id,
title: item.title,
content: item.content
}
});
}
return (
<div
className="tab-pane fade show active"
id="message"
role="tabpanel"
aria-labelledby="message-tab"
>
<ul className="news-list">
{messageState.map((item) => {
return (
<li key={item.id}>
<Link
to="detail"
state={{
id: item.id,
title: item.title,
content: item.content,
}}
>
{item.title}
</Link>
<button onClick={() => toDetailPage(item)}>前往详情</button>
</li>
);
})}
</ul>
<hr></hr>
<Outlet />
</div>
);
}
这样就实现了我们想要的效果。

3. Navigate的其他传参方式
上面的案例演示了编程式路通过state传参的过程,那如果想通过params或search传参呢?
其实很简单,只需要把参数拼接在url的后面就可以了!
- 通过 params 传参
javascript
navigate(`detail/${item.id}/${item.title}/${item.content}`);
- 通过 search 传参
javascript
navigate(`detail?id=${item.id}&title=${item.title}&content=${item.content}`);
4. 使用 Navigate 实现前进和后退
- 首先,我们将标题的部分封装成一个 Header 组件。
src/components/Header/index.jsx
javascript
import React from "react";
export default function Header() {
return (
<div className="row">
<div className="col">
<h1 className="header-title text-dark">React Router Demo</h1>
<span className="text-muted"></span>
</div>
</div>
);
}
- 然后,在
App.jsx中引入 Header 组件。
App.jsx
javascript
import { NavLink, useRoutes } from "react-router-dom";
import routes from "./routes"
import Header from "./components/Header";
import "./App.css";
function App() {
const element = useRoutes(routes);
return (
<div className="App">
<div className="container mt-4" style={{ maxWidth: "1000px" }}>
{/* 引入Header组件 */}
<Header />
<div className="row mt-4">
<div className="col-3">
<div className="list-group">
{/* 路由链接 */}
<NavLink
to="/about"
className="list-group-item list-group-item-action text-secondary"
>
About
</NavLink>
<NavLink
to="/home"
className="list-group-item list-group-item-action text-secondary"
>
Home
</NavLink>
</div>
</div>
<div className="col-9 content-area">
{/* 注册路由 */}
{element}
</div>
</div>
</div>
</div>
);
}
export default App;
- 在React Router v6中,不管是路由组件还是一般组件,只要想实现编程式路由导航,就直接使用 useNavigate Hook 即可。
src/components/Header/index.jsx
javascript
import React from "react";
import { useNavigate } from "react-router-dom";
import "./index.css";
export default function Header() {
const navigate = useNavigate();
return (
<div className="header row">
<div className="col">
<h1 className="header-title text-dark">React Router Demo</h1>
<span className="text-muted"></span>
<button className="btn btn-warning" onClick={() => navigate(-1)}>
后退←
</button>
<button className="btn btn-success" onClick={() => navigate(1)}>
前进→
</button>
</div>
</div>
);
}
这样前进和后退的效果就实现了。

九、useInRouterContext
useInRouterContext 用于检查当前组件是否被渲染在 Router 上下文内部,它返回一个布尔值(true 或 false)。
javascript
import { useInRouterContext } from 'react-router-dom';
function MyComponent() {
const isInRouter = useInRouterContext();
return (
<div>
{isInRouter ? <p>当前在路由环境中</p> : <p>当前不在路由环境中</p>}
</div>
);
}
十、useNavigationType
- 作用:返回当前的导航类型(用户是如何来到当前页面的);
- 返回值 :
POP、PUSH、REPLACE; - 备注 :
POP是指在浏览器中直接打开了这个路由组件(刷新页面);
javascript
import { useNavigationType } from 'react-router-dom';
const actionType = useNavigationType(); // 返回 POP, PUSH 或 REPLACE
十一、useOutlet
- 作用:用来返回当前路由层级下应当渲染的子路由内容。
javascript
import { useOutlet } from 'react-router-dom';
const result = useoutlet()
console.log(result)
// 如果嵌套路由没有挂载,则result为null
// 如果嵌套路由已经挂载,则展示嵌套的路由对象
我们可以在上面案例的Message组件中打印一下 useOutlet 的返回值:

十二、useResolvedPath
- 作用 :用于根据当前 url 来解析其中的 path 、search 、hash 值。
javascript
import { useResolvedPath } from "react-router-dom";
function MyComponent() {
const path = useResolvedPath('/abc/d/e?f=1&g=2&h=3#qwer');
console.log(path);
// path 的结构:
// {
// pathname: "/abc/d/e",
// search: "?f=1&g=2&h=3",
// hash: "#qwer"
// }
}
