0%

React Router 與 Hook 的邂逅

前言

在 React Hook 的風潮帶動下, React Router 在 v5.1 版的時候,
也 Release 了 useParams, useLocation, useHistory, useRouteMatch 的 Hooks,
接下來我會介紹這幾種 Hooks 的用法, 讓你的 React Router 也 Hook 起來吧。

useParams

以下範例是以往的寫法, 如果 URL 是 /portfolio/123, 就會 Match 到 Route, 並 Render Portfolio Component, Portfolio Component 的 props 裡面就有 Router 的一些資訊, 如果我們想要取得 URL 上的 id 資訊, 就可以從 props.match.params.id 取出 id 資訊為 “123”

程式範例(舊寫法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import { BrowserRouter as Router, Route, Switch, Link } from "react-router-dom";

const Portfolio = props => {
const { match } = props;
let {id} = match.params;
return (
<div>
Portfolio component
<p>Url params: {id}</p>
</div>
);
};

function App() {
return (
<div className="App">
<Router>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/contact">Contact</Link>
</li>
<li>
<Link to="/portfolio/6">Portfolio</Link>
</li>
</ul>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/portfolio/:id" component={Portfolio} />
<Route path="/contact" component={Contact} />
</Switch>
</Router>
</div>
);
}

程式範例(新寫法 Hook):

1
2
3
4
5
6
7
8
9
10
11
12
import { useParams} from "react-router";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";

const Portfolio = () => {
let { id } = useParams();
return (
<div>
Portfolio component
<p>Topic: {id}</p>
</div>
);
};

useLocation

useLocation 會回傳一個 Object 的物件, 裡面包含 pathname, search, hash, key 與 state 等資訊,
舉下面的範例, 我們可以透過 Link 的 to 屬性, 設定它 的 pathname 和 state, 我們就可以在 Settings Component 透過 useLocation 的 Hook 輕易的取得 pathname 和 state。

程式範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { useLocation} from "react-router";

const Settings = () => {
let location = useLocation();
console.log(location);
return <div>settings component</div>;
};


function App() {
return (
<div className="App">
<Router>
<ul>
<li>
<Link
to={{
pathname: "/settings",
state: {
fromNavBar: true
}
}}
>
Settings
</Link>
</li>
</ul>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/settings" component={Settings} />
</Switch>
</Router>
</div>
);
}

// console
// {
// "pathname": "/settings",
// "state": {
// "fromNavBar": true
// },
// "search": "",
// "hash": "",
// "key": "x8vmq3"
// }

useHistory

useHistory 會回傳一個物件, 裡面包含許多 navigation 方法, 例如: goBack 返回上一頁, push 到某一頁…等。

程式範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { useHistory } from "react-router-dom";

export const Profile = () => {
let history = useHistory();
console.log(history);
return (
<div>
<button onClick={() => history.goBack()}>Back</button>
<button onClick={() => history.push("/")}>Home</button>
<section>
<p>profile page</p>
</section>
</div>
);
};

useRouteMatch

接下來介紹最後一個 Hook 是 useRouteMatch, 這個 Hook 讓我們可以輕易 access match 這個屬性, 以往都要透過 Route Component 方式取得 match 屬性, useRouteMatch 跟 Route Component 的行為基本上是一樣的, 且寫起來更優雅。

以下為取得 match object 的方式:

  • Route component as this.props.match
  • Route render as ({ match }) => ()
  • Route children as ({ match }) => ()
  • withRouter as this.props.match
  • matchPath as the return value

程式範例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { useRouteMatch } from "react-router";

function App() {
let match = useRouteMatch({
path: "/Movies/:id/",
strict: true,
sensitive: true
});


return (
<div>
{match && <Movies match={match} />}
</div>
);
}

總結

介紹完以上的 Hook API, 相信可以導入到我們的專案上, 讓我們寫起來更方便且愉快 。

參考連結:

官方教學