React Router hooks 将使你的组件更简洁
作者:Nathan Sebhastian✏️
React Router 是一个轻量级库,允许您管理和处理 React 应用程序的路由。
React Router 最突出的特性之一是路由渲染方法,它使你的组件能够访问match
、location
和history
属性。这些属性一起用于将数据从 URL 传递到组件,并以编程方式导航你的 React 应用程序。
例如,如果你想创建一个返回按钮,你可以使用propsgoBack()
中的函数history
。这抽象了不同环境或浏览器之间的差异,让你可以用一个简单的函数返回上一个网页。
// a Route with component props
<Route path="/post/:number" component={Post} />
// The component itself
function Post(props) {
return (
<div>
In React Router v4, you get the history object from props. <br />
<button type="button" onClick={() => props.history.goBack()}>
Go back
</button>
</div>
);
}
虽然这工作正常,但路由的渲染方法被普遍认为难以阅读,而且非常奇怪。因此,从5.1 版本开始,React Router 将包含四个实用的钩子,你可以使用它们来编写简洁、整齐堆叠、赏心悦目的导航组件。我将通过与版本 4 中的旧模式进行比较,向你展示这些新钩子的工作原理。
我们将从钩子开始useParams
。
UseParams
该useParams
钩子将从您的应用程序 URL 返回一个设置为动态的键值对对象。在复杂的应用程序中,通常会有许多动态的导航链接。
例如,你可能有一个/post/:id
URL,它会向应用程序的后端发起一个获取过程。在这种情况下,最常见的 React Router 模式是使用组件 prop。
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/post/hello-world">First Post</Link>
</li>
</ul>
</nav>
<Switch>
<Route path="/post/:slug" component={Post} />
<Route path="/">
<Home />
</Route>
</Switch>
</div>
</Router>
);
}
通过将Post
组件传递到组件中/post/:number
Route
,您可以从 React Router 传递到组件中的 propparams
中提取对象。match
Post
// Old way to fetch parameters
function Post({ match }) {
let params = match.params;
return (
<div>
In React Router v4, you get parameters from the props. Current parameter
is <strong>{params.slug}</strong>
</div>
);
}
这种方法效果很好,但如果你的应用程序很大,包含大量动态路由,那么这种方法就相当繁琐了。你必须跟踪哪些Route
组件需要组件 props,哪些不需要。此外,由于match
对象是从渲染组件传递Route
到渲染组件的,你需要将它们传递给 DOM 树中更下游的组件。
这就是 hook 真正闪耀的地方useParams
。它是一个简洁的辅助函数,可以为你提供当前路由的参数,这样你就不必使用组件 props 模式了。
<Switch>
<Route path="/post/:slug" component={Post} />
<Route path="/users/:id/:hash">
<Users />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
function Users() {
let params = useParams();
return (
<div>
In React Router v5, You can use hooks to get parameters.
<br />
Current id parameter is <strong>{params.id}</strong>
<br />
Current hash parameter is <strong>{params.hash}</strong>
</div>
);
}
如果子组件Users
需要访问参数,您useParams()
也可以简单地在那里调用。
如果您想看看它的实际效果,这里有一个例子。
UseLocation
在 React Router 版本 4 中,就像获取参数一样,您必须使用组件 props 模式来访问location
对象。
<Route path="/post/:number" component={Post} />
function Post(props) {
return (
<div>
In React Router v4, you get the location object from props. <br />
Current pathname: <strong>{props.location.pathname}</strong>
</div>
);
}
在 5.1 版本中,您可以调用钩子从 React RouteruseLocation
获取对象。location
<Route path="/users/:id/:password">
<Users />
</Route>
// new way to fetch location with hooks
function Users() {
let location = useLocation();
return (
<div>
In React Router v5, You can use hooks to get location object.
<br />
Current pathname: <strong>{location.pathname}</strong>
</div>
);
}
再次,您可以在CodeSandbox上看到示例代码。
UseHistory
这让我们少了一个使用组件 props 的理由。但是,你仍然需要使用组件或渲染模式来获取history
对象吗?
对象history
是您需要使用组件或渲染道具模式的最后一个原因。
<Route path="/post/:slug" component={Post} />
// Old way to fetch history
function Post(props) {
return (
<div>
In React Router v4, you get the history object from props. <br />
<button type="button" onClick={() => props.history.goBack()}>
Go back
</button>
</div>
);
}
通过使用useHistory
钩子,您可以获得相同的历史对象,而无需Route
组件将其传递下去。
<Route path="/users/:id/:hash">
<Users />
</Route>
// new way to fetch history with hooks
function Users() {
let history = useHistory();
return (
<div>
In React Router v5, You can use hooks to get history object.
<br />
<button type="button" onClick={() => history.goBack()}>
Go back
</button>
</div>
);
}
请参阅此示例代码useHistory
以了解与常规道具之间的比较history
。
component
现在,您可以拥有一个简洁的路由组件,无需任何使用props的奇怪组件组合render
。您只需放置一个<Route>
带有 props 的组件path
,并将渲染的children
组件放入其中即可。
useRouteMatch
有时,您只需要使用<Route>
组件来访问match
对象。
<Route path="/post">
<Post />
</Route>
function Post() {
return (
<Route
path="/post/:slug"
render={({ match }) => {
return (
<div>
Your current path: <strong>{match.path}</strong>
</div>
);
}}
/>
);
}
上面的示例展示了一种match
不使用component
或render
props 来访问对象的方法。在最新版本的 React Router 中,你还可以使用useRouteMatch
钩子,它使你能够抓取match
对象并在组件内部使用它,而无需使用<Route>
。
<Route path="/users">
<Users />
</Route>
// useRouteMatch to make your route above cleaner
function Users() {
let match = useRouteMatch("/users/:id/:hash");
return (
<div>
In React Router v5, You can use useRouteMatch to get match object. <br /> Current match path: <strong>{match.path}</strong> </div> ); }
现在,你无需创建<Route>
组件来抓取match
对象了。这里有另一个示例供你参考。
结论
React Router 团队利用钩子的强大功能并实现它来跨组件共享逻辑,而无需从树的顶部向下传递它。
如果您想使用这些新钩子重构您的组件,您可以先更新使用match
、location
或history
对象的组件。
// before
function userComponent({ match, location, history }) {
let { slug } = match.params
// ...
}
// after
function userComponent() {
let { slug } = useParams()
let location = useLocation()
let history = useHistory()
// ...
}
之后,您可以更新<Route>
导航组件中可能存在的奇怪的组件。
// before
<Switch>
<Route path="/user/:id" component={userComponent} />
</Switch>
// after
<Switch>
<Route path="/user/:id">
<userComponent />
</Route>
</Switch>
你对 React Router Hooks 有什么看法?请在下方分享你的评论。
全面了解生产 React 应用程序
调试 React 应用可能很困难,尤其是当用户遇到难以复现的问题时。如果您对监控和跟踪 Redux 状态、自动显示 JavaScript 错误以及跟踪缓慢的网络请求和组件加载时间感兴趣,请尝试 LogRocket。
LogRocket就像 Web 应用的 DVR,可以记录 React 应用上发生的所有事件。您无需猜测问题发生的原因,而是可以汇总并报告问题发生时应用程序的状态。LogRocket 还可以监控应用的性能,并报告客户端 CPU 负载、客户端内存使用情况等指标。
LogRocket Redux 中间件包为您的用户会话增加了一层额外的可见性。LogRocket 会记录 Redux 存储中的所有操作和状态。
实现 React 应用程序调试方式的现代化 —开始免费监控。
React Router hooks 将使您的组件更清洁,该帖子首先出现在LogRocket 博客上。
文章来源:https://dev.to/bnevilleoneill/react-router-hooks-will-make-your-component-cleaner-3o70