React router dom 相關的 hook

一步一步累積。

簡述

雖然目前接觸的還不多,但如果之後有機會的話會慢慢把一些我覺得不錯用的 hook 給補上來。

useLocation

簡單來說就是會提供你跟「網址」相關的資訊,內容會長這樣:

1
2
3
4
5
6
7
{
"pathname": "/search",
"search": "",
"hash": "",
"state": null,
"key": "oaeqgk1p"
}

運用這個東西可以來實現導覽列 active 的狀態,假設我有一個 <Nav /> 內容如下:

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
import React, { useEffect } from "react";
import { Link } from "react-router-dom";

const Nav: React.FC = () => {

useEffect(() => {
console.log("path", location.pathname);
}, [location.pathname]);

return (
<ul>
<li>
<Link to="">Home</Link>
</li>
<li>
<Link to="about">About</Link>
</li>
<li>
<Link to="products">Products</Link>
</li>
<li>
<Link to="search">Search</Link>
</li>
</ul>
);
};

export default Nav;

我希望當我在 "" 的頁面時,<Link /> 時加上 active 的 className,其他的也是以此類推,那我就可以利用 location 來做這件事:

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 React, { useEffect } from "react";
import { Link, useLocation } from "react-router-dom";

const Nav: React.FC = () => {
const location = useLocation();

useEffect(() => {
console.log("path", location.pathname);
}, [location.pathname]);

return (
<ul>
<li>
<Link to="" className={location.pathname === "/" ? "active" : ""}>
Home
</Link>
</li>
<li>
<Link
to="about"
className={location.pathname === "/about" ? "active" : ""}
>
About
</Link>
</li>
<li>
<Link
to="products"
className={location.pathname === "/products" ? "active" : ""}
>
Products
</Link>
</li>
<li>
<Link
to="search"
className={location.pathname === "/search" ? "active" : ""}
>
Search
</Link>
</li>
</ul>
);
};

export default Nav;

這樣子就能實現囉!

雖然這應該不是最好的做法,畢竟有點 hard code。但主要是想介紹 useLocation 這個 hook 而已。

最後一樣附上範例

useNavigate 之 replace 的作用

useNavigate 最常見的用途是拿來跳轉頁面,這個大家應該都知道,所以這邊就不介紹了。這邊要介紹的是 replace 這個可選參數的用途。

假設我有一個網站,登入後才能進到首頁,那我可能就會在提交表單的時候用 useNavigate 來處理,像這樣:

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
import React from "react";
import { useNavigate } from "react-router-dom";

const Login: React.FC = () => {
const navigate = useNavigate();

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// 送出表單後導向首頁
navigate("/home");
};

return (
<div>
<h2>Login</h2>
<form onSubmit={handleSubmit}>
<div>
username: <input type="text" />
</div>
<div>
password: <input type="password" />
</div>
<button>submit</button>
</form>
</div>
);
};

export default Login;

可是這樣會有一個問題,就是我可以按「上一頁」來回到登入畫面:

(後來要補圖時卻做不出這效果…,總之確實是能回到上一頁的)

很詭異吧?所以 replace 就是這樣用的,只要改寫成這樣:

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
import React from "react";
import { useNavigate } from "react-router-dom";

const Login: React.FC = () => {
const navigate = useNavigate();

const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// 加上 replace: true
navigate("/home", { replace: true });
};

return (
<div>
<h2>Login</h2>
<form onSubmit={handleSubmit}>
<div>
username: <input type="text" />
</div>
<div>
password: <input type="password" />
</div>
<button>submit</button>
</form>
</div>
);
};

export default Login;

這樣就沒辦法回到上一頁啦!

solution

順道一提,如果你是用 <Link /> 來跳轉的話,它也有 replace 這個屬性可以用,功能是一模一樣的:

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

const Home: React.FC = () => {
return (
<div>
<h2>Welcome come back!</h2>
<p>Let's see some thing new.</p>
<Link to="../" replace={true}>
back
</Link>
</div>
);
};

export default Home;

最後,想看範例的話可以到這邊來看。

再探 mobx,換個口味的寫法 重溫 React router dom
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×