React - Router v6

React - Router v6

從 0 開始學 React

前言

今年 11 月初,React Router 更新到 v6 版本了,原本在參加 The F2E 活動的我,就邊做作品邊認識更新後所新增與移除的功能,雖然現在晚了,但終於有時間來做個筆記。

將原有的 <Switch> 升級為 <Routes>,並更新 <Route>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// v5
<Switch>
<Route exact path="/" component={ Home } />
<Route path="/resumes" render={() => (
<Resumes props={props} />
)}
/>
</Switch>

// v6
<Routes>
<Route path="/" element={<Home />} />
<Route path="resumes" element={<Resumes props={props} />} />
</Routes>

名稱改變,大部分功能沒變,並在 <Route> 新增 element 這個 props,使用起來更方便。

相對路由連接更簡單

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
/*  v5  */
// App.jsx
function App() {
return (
<Switch>
<Route path="/" component={ Home } />
<Route path="resumes" component={ Resumes } />
</Switch>
)
}

// Resumes.jsx
function Resumes() {
let { path, url } = useRouteMatch();
return (
<div>
<nav>
<Link to={`${url}/edit`}>編輯履歷</Link>
</nav>
<Switch>
<Route path={`${path}/edit`} component={ EditResumes } />
<Route path={`${path}/:id`} component={ OthersResumes } />
</Switch>
</div>
)
}

v6 就不需要使用 useRouteMatch()

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
/*  v6  */
// App.jsx
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="resumes" element={<Resumes />} />
</Routes>
)
}

// Resumes.jsx
function Resumes() {
return (
<div>
<nav>
<Link to='../'>上一層</Link>
<Link to='edit'>編輯履歷</Link>
</nav>
<Routes>
<Route path='edit' element={<EditResumes />} />
<Route path=':id' element={<OthersResumes />} />
</Routes>
</div>
)
}

如同上面的例子,不需要透過 useRouteMatch() 來完成嵌套路由了,同時可以使用 ../ 回到上一層路由,用法與 Command 的 cd 切換資料夾略同!

簡化巢狀路由,新增 <Outlet> 更方便管理

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
/*  這要跟上面的做比較  */
// App.jsx
function App() {
return (
<Routes>
<Route path="/" element={<Home />} />
<Route path="resumes" element={<Resumes />}>
<Route path='edit' element={<EditResumes />} />
<Route path=':id' element={<OthersResumes />} />
</Route>
</Routes>
)
}

// Resumes.jsx
function Resumes() {
return (
<div>
<nav>
<Link to='../'>上一層</Link>
<Link to='edit'>編輯履歷</Link>
</nav>
<Outlet />
</div>
)
}

新增 <Outlet> 把所有路由呈現的元件統一管理,依照 url 來呈現對應的 <Route>

使用 useRoutes 取代 react-router-config

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/*  這要跟上面的做比較  */
// App.jsx
function App() {
let element = useRoutes([
{ path: '/', element: <Home /> },
{
path: 'resumes',
element: <Resumes />
children: [
{ path: 'edit', element: <EditResumes /> },
{ path: ':id', element: <OthersResumes /> }
]
}
])
return element;
}

習慣使用 react-router-config 可以改使用 useRoutes 這個 Hook

使用 useNavigate 取代 useHistory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// v5
function Navbar() {
const history = useHistory();

const goHome = () => {
history.push('/home');
}
const goBack = () => {
history.goBack();
}
const goForward = () => {
history.goForward();
}
return (
<nav>
<button onClick={goHome}>回首頁</button>
<button onClick={goBack}>上一頁</button>
<button onClick={goForward}>下一頁</button>
</nav>
);
}

v6 換成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// v6
function Navbar() {
const navigate = useNavigate();

const goHome = () => {
navigate('/home');
}
const goBack = () => {
navigate(-1);
}
const goForward = () => {
navigate(1);
}
return (
<nav>
<button onClick={goHome}>回首頁</button>
<button onClick={goBack}>上一頁</button>
<button onClick={goForward}>下一頁</button>
</nav>
);
}

useHistory 的功能濃縮成 useNavigate,這個改動算是小改動吧~

其他

還有一些比較小的變更,可以查看官方文檔,這次的更新厲害的地方是,原本 20kb 縮小到 8kb,縮小了一半!

參考資料