简介
现代网站的页面,特别是**单页面应用程序(SPA)**并不遵循传统的方法,即每当页面有变化时就完全加载新的页面。 客户端路由(Client-Side Routing而是使用--当一个动作(如点击一个按钮或链接)被执行时,向资源路由,以加载程序的另一部分,或在结构上改变应用程序的整个视图。
React是一个大受欢迎的前端开发库,用于创建高度响应的用户界面,自然,它有自己的Router,执行客户端路由--react-router-dom 。
在本指南中,我们将看看如何使用React Router在React应用程序中创建路由,以编程方式在路由之间进行导航,以及在它们之间发送和检索数据。
创建一个React应用程序
让我们从通过命令行创建一个简单的React应用程序开始。
$ npx create-react-app router-sample
一旦创建,让我们进入项目的目录,并启动该应用程序。
$ cd router-sample
$ npm start
这将在localhost:3000 ,启动一个服务器,你的默认浏览器将启动以服务该应用程序。在创建任何新的文件为这个端点服务之前,让我们先安装react-router-dom ,因为它没有预先打包好。
安装React Router
像往常一样,使用npm 安装一个包就像运行一个命令一样简单。
$ npm install react-router-dom
使用React Router创建新的路由
react-router-dom 包使创建新路由变得简单。首先,你用<BrowserRouter> 标签来包装整个应用程序。我们这样做是为了获得对浏览器的history 对象的访问。然后,你定义你的路由器链接,以及每个路由将使用的组件。
为了证明这一点,让我们在/src 文件夹中创建一个名为About.js 的新文件。
const About = () => {
return (
<div>
<h1>About page here!</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugit, modi!
</p>
</div>
);
};
export default About;
现在,让我们更新src/index.js 页面,并从我们刚刚创建的文件中导入About 。在<BrowserRouter> 标签内,我们将定义我们的路由和与之相关的组件。
import { render } from "react-dom";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import About from "./About";
render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />} />
<Route path="about" element={<About />} />
</Routes>
</BrowserRouter>,
document.getElementById("root")
);
我们已经在这里导入了<BrowserRouter> ,并且我们已经将我们的整个应用程序包裹在它周围。我们还选择了App.js 作为我们主页的组件(在/ 端点下),以及About.js 作为/about 页面的组件。
最后,让我们调整一下App.js 文件,它将再次成为应用程序的主要入口点,并为我们的主页服务。
import { Link } from "react-router-dom";
function App() {
return (
<div className="App">
<h1>Welcome to my react app!</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus,
pariatur?
</p>
<br />
<Link to="/about">About Page</Link>
</div>
);
}
export default App;
在这个阶段,我们已经创建了两条路由:入口路由 (/) 和/about 路由,当我们访问我们的应用程序时,我们应该能够很容易地从主页导航到关于页面。

React Router Hooks(导航方法)
钩子最近被添加到React中,它是允许你 "钩住 "应用程序的状态的函数,而不需要编写新的类。React Router带有一些钩子,允许我们以编程方式访问Router状态并在组件之间导航。在这些钩子中,有以下几个。
useHistory()userNavigate()useLocation()useParams()
要使用这些钩子中的任何一个,我们必须首先从react-router-dom 包中导入它们,然后指定一个调用钩子的变量;我们将在接下来的章节中详细介绍。
useHistory()
**注意:**在最新版本的React Router中,useHistory() 钩子已经被弃用。如果你正在使用React Router V6,你会想使用useNavigate() 钩子来代替。它就在useHistory() 之后。
useHistory() 钩子提供了对React Router的历史实例的直接访问,使我们能够执行诸如检索历史堆栈中的条目数量,添加、改变或从堆栈中删除条目等操作。
这里的一些最有用的方法包括。
goBack()- 在历史中往后走。goForward()- 在历史中往前走。push()- 在历史堆栈中添加一个新条目,即导航到一个新的URL。replace()- 类似于 ,它取代了历史中的当前堆栈,但与 ,用户不能在历史中回溯,即点击浏览器的返回按钮不会返回到以前的状态。push()push()
就这样,我们可以通过程序化的方式从我们的About 页面导航到主页,通过push()在历史记录中输入一个新条目,有效地将用户导航到新条目。
import React from "react";
import { useHistory } from "react-router-dom";
const About = () => {
let history = useHistory();
const goHome = () => {
history.push("/");
};
return (
<div>
<h1>About page here!</h1
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugit, modi!
</p>
<button onClick={goHome}>Go to home page</button>
</div>
);
};
export default About;
在这里,我们只是导入了useHistory() 钩子,并创建了一个新的goHome() 函数,在点击按钮时执行。这只是对push() 调用的一个包装。
我们还可以转移状态或发送任意数据到我们正在导航的路线。我们可以通过向推送方法发送一个对象而不是作为字符串的路径名来做到这一点,并将我们的状态添加到一个不同的对象。
history.push({
pathname: '/blog,
search: '?blogId=12, // Query string
state: { // Location state
author_name: "John Doe",
},
});
在介绍了useNavigate() 之后,我们将看看如何使用useLocation() 和useParams() 钩子来访问这些数据。
useNavigate()
如果你使用的是React Router的最新版本,useHistory() 钩子已经被弃用,转而使用useNavigate() 。这个方法几乎是相同的;主要的区别是,useNavigate() 钩子不接受像.push() 或.replace() 这样的方法。你只是navigate() 到某个条目。
import React from "react";
import { useNavigate } from "react-router-dom";
const About = () => {
let navigate = useNavigate();
const goHome = () => {
navigate("/");
};
return (
<div>
<h1>About page here!</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugit, modi!
</p>
<button onClick={goHome}>Go to home page</button>
</div>
);
};
export default About;
当然,这种方法也允许我们在路由之间转移状态。
navigate("/blog", { state: { author_name: "John Doe" } });
用*useLocation()和useParams()*在路由之间检索数据
useLocation() 钩子为我们提供了对浏览器的location 对象的访问。把它看作是负责获取当前路由的必要信息的钩子。
import { useNavigate, useLocation } from "react-router-dom";
/*...*/
let location = useLocation();
console.log(location);
运行上面的代码应该返回关于当前路由的所有信息,如下图所示。
{
"pathname": "/about",
"search": "",
"hash": "",
"state": null,
"key": "default"
}
把useLocation() 钩子看作是useState() 钩子是合理的,每当URL发生变化时,它就会把状态更新到一个新的位置。另一方面,userParams() 钩子可以用来获取URL参数的值。当被调用时,useParams() 提供一个对象,将URL参数的名称映射到它们在当前URL中的值。
例如,在我们的路由器配置中,假设我们已经有了一个动态路由。
<Route path="/about/:user_id">
<About />
</Route>
而在另一个页面,我们有一个链接组件,指向与用户2有关的一些信息。
<Link to="/about/2">About User 2</Link>
当参数被传递时,就像我们之前看到的那样--我们可以通过userParams() 钩子访问这些参数。
import { useParams } from "react-router-dom";
const About = () => {
const { user_id } = useParams();
return (
<div>
<h1>About user {user_id}</h1>
<p>
Lorem ipsum dolor...
</p>
</div>
);
};
export default About;
结论
React Router用于资源的客户端路由。在本指南中,我们快速浏览了如何使用React Router以编程方式浏览应用程序,以及在浏览时如何在路由之间转移状态。