iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 17
1

在網頁中最常使用的操作肯定要有透過導航列切換頁面這一個功能,而在 React 中我們可以透過 React router 的方式達成切換元件,渲染對應元件的內容來達成就像是跳轉到該頁面的目的。

意思是在 React 中,透過 router 切換的 url 並非是真正的跳轉至具有該 url 的頁面,透過這個 path 用來切換的是我們寫在 React 中的元件。

後續幾天的篇幅會搭配著文件提供的部分範例來學習在不是使用 hook 與使用 hook 下的不同寫法。

接著讓我們來學習關於 router 常用的一些方式吧!

使用 react-router-dom 套件

這是一套並非由 Facebook 團隊開發的套件,但是在 React 中卻廣為被應用於配置路由的套件。

首先,我們先進行安裝:

npm i --save react-router-dom

接著再往下設定基礎的 router 之前,我們要先了解組成 React router 最重要的三個部分:

根據這個套件的文件描述:

  • routers, like <BrowserRouter> and <HashRouter>
  • route matchers, like <Route> and <Switch>
  • and navigation, like <Link>, <NavLink>, and <Redirect>

接著我們先看看這幾個重要的組成的用途

routers

首先是 routers,區分為 <BrowserRouter> 以及 <HashRouter>,差異如下:

透過 <BrowserRouter> 方式呈現的 URL 更貼近於我們平常在使用的 URL,但這個部分需要注意和後端的設定做配置,否則可能容易導致 404 的情形發生。

<HashRouter> 方式則是多了一個 /#/,雖然不貼近於我們使用的 URL,但是並不需要注意後端的配置是否會影響。

route matchers

接著是 route matchers,<Route> 以及 <Switch>,透過 <Switch> 可以用來包住 <Route> ,將 <Route> 作為它的 children。並且 <Switch> 只會渲染第一個符合匹配的路徑(即使還有另外一個符合的路徑。)

<Route> 則是用來將符合匹配路徑的元件內容渲染出來。

此外,文件中提到在使用 <Route path> 需要注意的部分: path 從 URL 的開頭進行匹配,而非是整個 path。

舉個例子: 我們可能會有如下這個 router設置:

<Route path="/">
<Route path="/page">

在上述的設定中, path 永遠只匹配 / 這個路徑,因此為了避免這個部分,有幾種做法:

  1. <Route path="/"> 移動到所有 router 配置的最後方
  2. 透過 exact 明確表示要匹配完整 path

所以會變成如下兩種方式:

<Route path="/page">
<Route path="/">

或者

<Route exact path="/">
<Route path="/page">

另外要提的部分是,如果有查閱文件的話,會發現有三種方式可以 render component:

  • <Route component>
  • <Route render>
  • <Route children> function

至於為什麼有這幾種不同的方式,可以從這篇 Difference between passing component to Route as prop and wrapping component in render function stackoverflow 中的回答可以有比較多的了解。

基本上在 react-router v5 之前只有 <Route component><Route render> 這兩種方式,而在 v5 之後提供了<Route children> function,而這幾個方式的實作上有著什麼差異呢?

首先是透過 <Route component> 的方式,這個方式是使用 React.createElement 的方式每次都產生一個新的 react element,當如果是透過內聯函式的方式設定,比如這個寫法:

<Route component={() => (<Bar id={this.state.id}/>)}/>

則會造成元件不斷的在 mount 與 unmount 導致效率很低。

然後是 <Route render>,這個方式則不會有 <Route component> 的問題,並不會導致元件不斷的在 mount 與 unmount。但需要注意的是如果同時使用 <Route component><Route render> 的話,前者優先權比後者高。

接著是 <Route children> function,用法與 <Route render> 基本上沒有差異,差別只在當 route 沒有 match 到 URL 時, 此時 match 的值會是 null ,並且可以動態調整 UI 等。

可以參考官方的這個 範例

navigation

最後是 <Link>, <NavLink>, 以及 <Redirect>,用途如下:

  • <Link>: 用來導航至你要渲染出來的元件,在 HTML 中會是以 <a> 的方式呈現
  • <NavLink>: 也是一種 <Link>,但差別在於可以自訂點擊該連結時的效果,透過搭配 activeClassName 來使用,並且當路徑中有 "/" 設定時,需搭配 exact 明確指出需要完整匹配路徑才可以觸發 active style
  • <Redirect>: 用於頁面重整等等時,作為重導向到指定路徑使用

接著我們透過上述的理解與文件中 Quick Start 的範例,改寫一個比較簡單的例子來學習:

這裡只提供關於 router 配置的部分,相關測試範例,點擊前往

  import React from "react";
  import "./styles.css";
  import PageA from "./containers/PageA";
  import PageB from "./containers/PageB";

  import {
    BrowserRouter as Router,
    Switch,
    Route,
    Link,
    NavLink,
    Redirect
  } from "react-router-dom";

  export default function App(props) {
    return (
      <div className="App">
        <Router>
          <h2>使用 Link</h2>
          <nav>
            <ul>
              <li>
                <Link to="/PageA">PageA</Link>
              </li>
              <li>
                <Link to="/PageB">PageB</Link>
                <Redirect to="/" />
              </li>
            </ul>
          </nav>
          <h2>使用 NavLink</h2>
          <nav>
            <ul>
              <li>
                <NavLink to="/PageA" activeClassName="active">
                  PageA
                </NavLink>
              </li>
              <li>
                <NavLink to="/PageB" activeClassName="active">
                  PageB
                </NavLink>
                <Redirect to="/PageA" />
              </li>
            </ul>
          </nav>
          <Switch>
            <Route path="/PageA">
              <PageA />
            </Route>
            <Route path="/PageB">
              <PageB />
            </Route>
          </Switch>
        </Router>
      </div>
    );
  }

上述範例展示如何透過 router 切換路由,分為幾個部分:

  • <Link><NavLink><Route> 都要寫在 <Router> 中(這裡的 <Router> 指的是 <BrowserRouter> 或者 <HashRouter>)
  • <Route> 中指定路徑,渲染對應的元件
  • <Link><NavLink> 中指定要前往的路徑,若符合匹配,則會切換並渲染該元件的內容。
  • <Link><NavLink> 差別只在於點擊時是否有被點擊(active)的效果。
  • 可以修改 <Switch> 中的 <Route path="/pageA"><Route path="/pageB">,理解 <Switch> 的用意:只會渲染第一個符合匹配的路徑(即使還有另外一個符合的路徑。)

了解了基本的配置方式之後,明天我們接著學習幾個常用的 router 配置方式。

鐵人賽文章與程式碼同步發佈於:

  1. 個人部落格
  2. Github

資源


上一篇
在 React 中執行非同步請求
下一篇
React router 配置動態參數並取得 api 資料內容
系列文
與 React 交朋友的三十天學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言