React Router 5 充分利用了 hooks 的强大功能,并引入了四个不同的 hooks 来帮助进行路由。 如果你正在寻找 React Router 新模式的快速入门指南,你会发现这篇文章很有用。 但在我们了解 hooks 之前,我们将从一个新的路由渲染模式开始。
React Router 5 之前
// When you wanted to render the route and get router props for component
<Route path="/" component={Home} />
// Or when you wanted to pass extra props
<Route path="/" render={({ match }) => <Profile match={match} mine={true} />}>
使用 component
语法时,路由 props(match
、location
和 history
)会隐式地传递给组件。 但是,一旦你需要将额外的 props 传递给组件,就必须将其更改为 render
。 请注意,向 component
语法添加内联函数会导致组件在每次渲染时重新挂载。
React Router 5 之后
<Route path="/">
<Home />
</Route>
请注意,没有将任何 props 隐式传递给 Home
组件。 但无需更改 Route
本身,你可以向 Home
组件添加任何额外的 props。 你不再会犯在每次渲染时重新挂载组件的错误,这是最好的 API。
但是现在路由 props 没有被隐式传递,那么我们如何访问 match
、history
或 location
呢? 我们是否必须用 withRouter
包装所有组件? 这就是 hooks 发挥作用的地方。
请注意,hooks 是在 React 16.8 版本中引入的,因此你需要使用高于该版本的 React 来使用它们。
useHistory
- 提供对 React Router 中
history
prop 的访问。 - 指的是路由器使用的 history 包 依赖项。
- 主要用例是使用函数(如
push
、replace
等)进行编程路由。
import { useHistory } from 'react-router-dom';
function Home() {
const history = useHistory();
return <button onClick={() => history.push('/profile')}>Profile</button>;
}
useLocation
- 提供对 React Router 中
location
prop 的访问。 - 它类似于浏览器本身中的
window.location
,但它在任何地方都可访问,因为它表示路由器状态和位置。 - 此功能的主要用例是访问查询参数或完整的路由字符串。
import { useLocation } from 'react-router-dom';
function Profile() {
const location = useLocation();
useEffect(() => {
const currentPath = location.pathname;
const searchParams = new URLSearchParams(location.search);
}, [location]);
return <p>Profile</p>;
}
由于 location
属性是不可变的,因此 useEffect
会在每次路由更改时调用该函数,使其非常适合操作搜索参数或当前路径。
useParams
- 提供对 URL 中搜索参数的访问。
- 以前只能使用
match.params
来实现这一点。
import { useParams, Route } from 'react-router-dom';
function Profile() {
const { name } = useParams();
return <p>{name}'s Profile</p>;
}
function Dashboard() {
return (
<>
<nav>
<Link to={`/profile/ann`}>Ann's Profile</Link>
</nav>
<main>
<Route path="/profile/:name">
<Profile />
</Route>
</main>
</>
);
}
useRouteMatch
- 提供对
match
对象的访问。 - 如果它不带任何参数提供,它将返回组件或其父组件中最接近的匹配项。
- 主要用例是构建嵌套路径。
import { useRouteMatch, Route } from 'react-router-dom';
function Auth() {
const match = useRouteMatch();
return (
<>
<Route path={`${match.url}/login`}>
<Login />
</Route>
<Route path={`${match.url}/register`}>
<Register />
</Route>
</>
);
}
你还可以使用 useRouteMatch
在不渲染 Route
的情况下访问匹配项。 这是通过将 location 参数传递给它来完成的。
例如,假设你需要在 /profile
处渲染你自己的个人资料,如果 URL 包含该人的姓名 /profile/dan
或 /profile/ann
,则渲染其他人的个人资料。 在不使用 hook 的情况下,你将要么编写一个 Switch
,列出两个路由并使用 props 自定义它们。 但现在,使用 hook,我们可以这样做
import {
Route,
BrowserRouter as Router,
Link,
useRouteMatch,
} from 'react-router-dom';
function Profile() {
const match = useRouteMatch('/profile/:name');
return match ? <p>{match.params.name}'s Profile</p> : <p>My own profile</p>;
}
export default function App() {
return (
<Router>
<nav>
<Link to="/profile">My Profile</Link>
<br />
<Link to={`/profile/ann`}>Ann's Profile</Link>
</nav>
<Route path="/profile">
<Profile />
</Route>
</Router>
);
}
你还可以将 Route
上的所有 props(如 exact
或 sensitive
)作为对象与 useRouteMatch
一起使用。
总结
hooks 和显式的 Route
本身就具有一个隐藏的优势。 在多个研讨会上教授了这些技巧之后,我意识到这些技巧有助于避免早期模式带来的许多困惑和复杂性。 突然之间,非强制性错误要少得多。 它们肯定会帮助你使路由器代码更易于维护,并且你会发现升级到新的 React Router 版本变得更容易。
如果我的 React 应用程序在子文件夹(而不是根路径)等位置初始化。 React Router 在这些情况下如何工作? React Router 匹配 hook 在 React 应用程序在已存在路径内初始化的这些情况下是否有效。
BrowserRouter 有一个用于
baseName
的配置,可用于使用基本路径对其进行初始化。 在 文档 中查看它好文章
我真的很喜欢这种新的语法。 它比旧方法 **好得多**
Hooks 再次将它连接起来
天啊,使用 hooks 看起来好多了!!!
这些功能从哪个版本的 react-router-dom 开始可用?
React Router 5.1
这会发送两个请求,第一个在挂载时发送,第二个在位置更改时发送。 如何使其仅在挂载时运行一次…?