現(xiàn)代化 React 路由 Hookrouter 的使用
Hookrouter 開發(fā)使用路由在單頁應(yīng)用程序頁面中導(dǎo)航和初始化狀態(tài)是至關(guān)重要的。Hookrouter 模塊為處理 React 應(yīng)用程序中的路由提供了一個更好方案。
原文地址:Hookrouter: A Modern Approach to React Routing 原文作者:Isuri Devindi 譯文出自:掘金翻譯計劃 本文永久鏈接:github.com/xitu/gold-m… 譯者:Zz 招錦 校對者:PassionPenguin、KimYang

路由在單頁應(yīng)用程序(SPA)頁面中導(dǎo)航和初始化狀態(tài)是至關(guān)重要的。對于 React,大多數(shù)開發(fā)者都使用過 react-router-dom,這是 Reactrouter 庫用于路由的一個變量。
然而,隨著 React hooks 的引入,最近一個被稱為 Hookrouter 的新模塊被推出,作為一個基于 hooks 的靈活、快速的路由。
本文將重點介紹我們?nèi)绾问褂?Hookrouter 模塊來實現(xiàn) Reactrouter 的基本功能。
為了演示 Hookrouter 的功能,我將使用一個商城作為示例,有四個基本組件,即 Nav.js、Home.js、About.js 和 Shop.js。此外,使用 Hookrouter 作為路由的完整 React 應(yīng)用程序可以在這里找到。
Hookrouter 與 Reactrouter 定義路由對比
當(dāng)使用 Reactrouter 時,我們可以按以下方式定義路由。
import Nav from './components/Nav';
import About from './components/About';
import Shop from './components/Shop';
import Home from './components/Home';
import {BrowserRouter as Router,Route} from'react-router-dom';
function App() {
return (
<Router>
<div class>
<Nav/>
<Route path = '/' component = {Home}/>
<Route path = '/about' component = {About}/>
<Route path = '/shop' component = {Shop}/>
</div>
</Router>
);
}
export default App;
復(fù)制代碼
我希望大家都能熟悉上述這些相對簡單的示例。
如果我們使用 Hookrouter 來實現(xiàn),那么可以使用 useRoutes() hook 將路由聲明為一個對象。
對象的鍵定義了路徑,而對象的值是路徑匹配時觸發(fā)的函數(shù)。路由器一個接一個地檢查路徑,在找到匹配后停止檢查。
import {useRoutes} from 'hookrouter'
import Nav from './components/Nav';
import About from './components/About';
import Shop from './components/Shop';
import Home from './components/Home';
function App() {
const routes = {
'/' :()=><Home/>,
'/about' :()=> <About/>,
'/shop' :()=> <Shop/>,
};
const routeResults = useRoutes(routes);
return (
<div class>
<Nav/>
{routeResults}
</div>
);
}
export default App;
復(fù)制代碼
Reactrouter 中的 <Route/> 組件每次都必須被渲染,同時還有應(yīng)用程序中每個路由的所有 props。然而,在 Hookrouter 中,定義為對象的路由可以簡單地傳遞給 useRoutes() hook。
注意: 確保在組件之外創(chuàng)建路由對象;否則,整個對象將在每次渲染時被重新創(chuàng)建。
Hookrouter 實現(xiàn) Reactrouter 開關(guān)功能
<Switch> 是用來渲染路由的,只渲染與位置相匹配的第一個孩子 <Route> 或 <Redirect>。當(dāng)定義的導(dǎo)航路由不匹配時,<Switch> 通常被用來呈現(xiàn) 404 頁面。
讓我們來看看如何使用 <Switch> 來用 Reactrouter 路由呈現(xiàn) 404 頁面。
import Nav from './components/Nav';
import About from './components/About';
import Shop from './components/Shop';
import Home from './components/Home';
import Error from './components/Error';
import {BrowserRouter as Router, Switch,Route} from'react-router-dom';
function App() {
return (
<Router>
<div class>
<Nav/>
<Switch>
<Route path = '/' exact component = {Home}/>
<Route path = '/about' component = {About}/>
<Route path = '/shop'exact component = {Shop}/>
<Route><Error/> </Route>
</Switch>
</div>
</Router>
);
}
export default App;
復(fù)制代碼
當(dāng)使用 Hookrouter 進(jìn)行路由時,由于路由是在一個對象中定義的,所以需要專門渲染,
useRoutes()hook 在默認(rèn)情況下執(zhí)行<Switch>組件的功能。
例如,使用 Hookrouter 路由呈現(xiàn) 404 頁面,我們只需傳遞我們想要顯示的錯誤或包含錯誤信息的組件進(jìn)行渲染,如下所示(第 17 行)。
import {useRoutes} from 'hookrouter'
import Nav from './components/Nav';
import About from './components/About';
import Shop from './components/Shop';
import Home from './components/Home';
function App() {
const routes = {
'/' :()=><Home/>,
'/about' :()=> <About/>,
'/shop' :()=> <Shop/>,
};
const routeResults = useRoutes(routes);
return (
<div class>
<Nav/>
{routeResults||<h1>PAGE NOT FOUND</h1>}
</div>
);
}
export default App;
復(fù)制代碼
注意: 我發(fā)現(xiàn)一個重要事實是,在 Reactrouter
<Switch>中,如果沒有明確指明路由導(dǎo)航,在某些情況下可能導(dǎo)致路由錯誤。
例如,如果到 {Home} 的路徑?jīng)]有明確指明,應(yīng)用程序?qū)⒉粫?dǎo)航到任何其他以 / 開頭的路徑。因此,應(yīng)用程序不會路由導(dǎo)航到 {About} 或 {Shop} 組件,而會一直路由導(dǎo)航到主頁。然而,在 Hookrouter 中,由于路由是作為一個對象來聲明的,所以不需要明確聲明導(dǎo)航路徑。
使用 Hookrouter 導(dǎo)航
通過 Reactrouter 使用 <Link> 來在整個應(yīng)用中導(dǎo)航。此外,在 React 應(yīng)用中,可以用它來定制和交互式地管理導(dǎo)航。
import React from 'react'
import {Link} from 'react-router-dom'
function Nav() {
return (
<div>
<nav>
<ul className='nav-links'>
<Link className='Link' to='/'>
<li>HOME</li>
</Link>
<Link className='Link' to='/about'>
<li>ABOUT</li>
</Link>
<Link className='Link' to='/shop'>
<li>SHOP</li>
</Link>
</ul>
</nav>
</div>
)
}
export default Nav
復(fù)制代碼
Hookrouter 使用一個
<A>組件來提供<Link>組件的功能。<A>是一個來自 HTML 的<a>標(biāo)記的包裝器,與錨標(biāo)記的功能完全兼容。
<A> 和 <Link> 之間的主要區(qū)別是,<A> 將 URL 推送到歷史棧,而不加載新的頁面。因此,onclick 函數(shù)必須由 <A> 組件包裝,以攔截點擊事件,停止默認(rèn)行為并將 URL 推送到歷史堆棧。
import React from 'react'
import {A} from 'hookrouter'
function Nav() {
return (
<div>
<nav>
<ul className='nav-links'>
<A className='Link' href='/'>
<li>HOME</li>
</A>
<A className='Link' href='/about'>
<li>ABOUT</li>
</A>
<A className='Link' href='/shop'>
<li>SHOP</li>
</A>
</ul>
</nav>
</div>
)
}
export default Nav
復(fù)制代碼
處理動態(tài)路由
一些組件包含動態(tài)部分,必須根據(jù) URL 的要求進(jìn)行渲染。URL 參數(shù)被用來在 URL 中設(shè)置動態(tài)值。在 Reactrouter 中,占位符被傳遞給 <Route/> 組件中以冒號開始的路徑道具。
為了證明這個判斷,讓我們考慮在應(yīng)用程序的商店頁面上顯示一個產(chǎn)品列表。當(dāng)用戶點擊某個特定產(chǎn)品時,他們應(yīng)該被引導(dǎo)到該產(chǎn)品的詳細(xì)信息頁面。導(dǎo)航是動態(tài)進(jìn)行的,在路徑道具中傳遞產(chǎn)品 ID 作為占位符。
<Route path = '/shop/:id' component = {Details}/>
復(fù)制代碼
在 Hookrouter 中,URL 參數(shù)的傳遞方式與 Reactrouter 中的方式相同,結(jié)構(gòu)也是一樣的。
const routes = {
'/shop/:id':({id})=><Details id={id}/>
};
復(fù)制代碼
然而,Hookrouter 對 URL 參數(shù)的處理方式不同。
它使用路由對象中定義的鍵來讀取 URL 參數(shù)。 將它們放入一個對象中,命名的參數(shù)將作為一個組合對象被轉(zhuǎn)發(fā)給路由結(jié)果函數(shù)。 使用對象解構(gòu)從中提取動態(tài)屬性,然后可以應(yīng)用于相關(guān)組件。
因此,正如你所看到的,使用 Reactrouter 獲得的結(jié)果同樣可以通過 Hookrouter 實現(xiàn)。
Hookrouter 的其他特性
程序化導(dǎo)航
使用 Hookrouter 依賴包的 navigate(url, [replace], [queryParams]) 函數(shù),可以用來將用戶發(fā)送到一個提供的絕對或相對 URL 定義的特定頁面。例如,要導(dǎo)航到關(guān)于頁面,可以使用下面的代碼片段。
navigate(‘/about’)
復(fù)制代碼
navigate() 默認(rèn)是一個向前的導(dǎo)航。因此,將在瀏覽歷史中創(chuàng)建一個新的條目,用戶可以點擊瀏覽器中的后退按鈕,回到前一頁。
重定向
Hookrouter 借助于 useRedirect() hook 來處理重定向問題。它需要一個源路由和一個目標(biāo)路由作為參數(shù)。
useRedirect('/', '/greeting');
復(fù)制代碼
每當(dāng) / 路徑被匹配,useRedirect() 將自動將用戶重定向到 /greeting 路徑。
這個 hook 會觸發(fā)一個替換的路由導(dǎo)航。因此,在導(dǎo)航歷史中,將只有一個條目。因此,如果重定向從 / 發(fā)生到 /greeting,如最后一個代碼片斷所示, / 路線將不會出現(xiàn)在瀏覽歷史中。
許多其他 Reactrouter 庫的功能(除了這里討論的那些)可以使用 Hookrouter 模塊實現(xiàn),如嵌套路由、懶加載組件和服務(wù)器端渲染。
此外,請隨時查看 Hookrouter 文檔,了解更多關(guān)于這個模塊的信息。
不足之處
我注意到,有時 Hookrouter 在最新版本默認(rèn)啟用嚴(yán)格模式的 create-react-app 中無法工作。
然而,你只需要從 index.js 中刪除 <React.StrictMode> 組件就可以使用 Hookrouter。
<React.StrictMode>
<App />
</React.StrictMode>
復(fù)制代碼
另一個缺點是,由于這個模塊相對較新。它可能包含一些未知的和不尋常的錯誤,從而導(dǎo)致發(fā)生意外結(jié)果。
本文總結(jié)
從上面的示例可以看出,Hookrouter 模塊為處理 React 應(yīng)用程序中的路由提供了一個更簡潔、更快速、更靈活的選擇。
它提供了 Reactrouter 庫的大部分功能。因此,我鼓勵你去嘗試一下,先在小型項目中使用它。
謝謝你的閱讀!
如果發(fā)現(xiàn)譯文存在錯誤或其他需要改進(jìn)的地方,歡迎到 掘金翻譯計劃 對譯文進(jìn)行修改并 PR,也可獲得相應(yīng)獎勵積分。文章開頭的 本文永久鏈接 即為本文在 GitHub 上的 MarkDown 鏈接。
掘金翻譯計劃 是一個翻譯優(yōu)質(zhì)互聯(lián)網(wǎng)技術(shù)文章的社區(qū),文章來源為 掘金 上的英文分享文章。內(nèi)容覆蓋 Android、iOS、前端、后端、區(qū)塊鏈、產(chǎn)品、設(shè)計、人工智能等領(lǐng)域,想要查看更多優(yōu)質(zhì)譯文請持續(xù)關(guān)注 掘金翻譯計劃、官方微博、知乎專欄。

如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:
點個「在看」,讓更多的人也能看到這篇內(nèi)容(喜歡不點在看,都是耍流氓 -_-) 歡迎加我微信「TH0000666」一起交流學(xué)習(xí)... 關(guān)注公眾號「前端Sharing」,持續(xù)為你推送精選好文。
