iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 19
3
Modern Web

一步一腳印的React旅程系列 第 19

[筆記][React]React網頁好朋友Router(3)-Switch和轉址王Redirect

Hi啊大家好!這幾天我一直在想該怎麼打出一篇好文章(雖然鐵人賽都過一半了XD),但這也是鐵人賽一路走來才會思考到的事情吧?在一天一篇文章持續30天的過程中,該怎麼規劃每天的內容以及文章的長度,就會變得比平常更重要!所以該怎麼說,後半段可能變成在摸索平衡的過程,如果各位大大有任何建議再請賜指教了!謝謝大家!

今天的題外話比較長,那我們繼續學習玩轉Router的技巧吧!


Switch

Switch也是react-router-dom的組件之一,我們可以用它包住多個Route,在這種情況下Switch會控制只有在第一個Route符合path時才會渲染,假設以下例子:

//目前網址為:/about
//匯入Switch組件
import { Route, Switch } from "react-router-dom"

<Switch>
    <Route exact path="/" component={Home} />  //(1)
    <Route path="/about" component={About} />  //(2)
    //雖然也符合網址的條件,但是因為在Switch中只會渲染第一個符合條件的Route
    <Route path="/:type" component={type} />  //(3)
</Switch>
  1. Route加上了exact,網址要嚴格等於根目錄/才符合條件,因此不會渲染組件。
  2. 網址符合Route設定的path,所以會被渲染。
  3. 雖然用參數的方式也符合,但因為在Switch內只會進入第一個符合的Route,所以在(2)之後的Route就算網址符合path也不會進入。

那這有什麼用呢?假設當前的網址目錄我們還沒完成要渲染的頁面,又不想讓使用者看見瀏覽器出現錯誤的畫面(應該也不會,只是沒有組件被渲染而已),該怎麼辦?讓我們繼續修改鞭屍About.jsx的內容吧XD,新朋友可以從Github這裡下載

之前的例子中在關於我們內有「理念介紹」和「歷史沿革」,以下將再加入「品牌故事」,以及網頁建構中的組件:

import React from "react"
import { Route, Link, Switch } from "react-router-dom"

class About extends React.Component {
    render() {
        return (
            <div>
                <h2>關於我們選單</h2>
                <ul>
                    <li><Link to={`${this.props.match.url}`}>理念介紹</Link></li>
                    <li><Link to={`${this.props.match.url}/his`}>歷史沿革</Link></li>
                    <li><Link to={`${this.props.match.url}/story`}>品牌故事</Link></li>
                </ul>
                <Switch>
                    <Route exact path={`${this.props.match.path}`} component={Introd} />
                    <Route path={`${this.props.match.path}/his`} component={His} />
                    <Route component={NoPage} />
                </Switch>
            </div>
        )
    }
}

class Introd extends React.Component {
    render() {
        return <p>這裡是理念介紹</p>
    }
}

class His extends React.Component {
    render() {
        return <p>這裡是歷史沿革</p>
    }
}

class NoPage extends React.Component {
    render() {
        return <p>頁面維護中...</p>
    }
}

export { About }

上方在品牌故事的Link中設定了to={`${this.props.match.url}/story`}但我們沒有還沒做好story的組件,於是先建立了一個沒設定pathRoute,也因為沒有設定,所以不論任何情況,該Route都會符合進入渲染組件,但我們加入了Switch就會讓狀況完全不一樣,只要該Route之前有任何其他符合的Route那最後一個NoPage就不會被渲染。
Github程式連結
GitPage頁面連結

轉址王Redirect

這個組件也是react-router-dom裡面的東西,為什麼叫轉址王呢?其實只有我取啦!其實官方叫他重定向,哈哈哈,主要是因為這個組件能夠用form設定符合的url,再將該url轉到設定的to中,這樣會很抽象嗎?哈哈哈,讓我們來看看!下方的About.jsx每次都是他XD,不過這次我們只需要看Aboutclass

class About extends React.Component {
    render() {
        return (
            <div>
                <h2>關於我們選單</h2>
                <ul>
                    <li><Link to={`${this.props.match.url}`}>理念介紹</Link></li>
                    <li><Link to={`${this.props.match.url}/his`}>歷史沿革</Link></li>
                    <li><Link to={`${this.props.match.url}/story`}>品牌故事</Link></li>
                </ul>
                <Switch>
                    <Route exact path={`${this.props.match.path}`} component={Introd} />

                    {/*(1)*/}
                    <Route path={`${this.props.match.path}/his`} component={His} />
                    <Redirect from={`${this.props.match.path}/story`} to={`${this.props.match.url}/his`} />
                </Switch>
            </div>
        )
    }
}

在程式碼中註解(1)的地方多加了RedirectSwitch中,他裡面有個from,意思是當目前的Link連結到${this.props.match.path}/story這個路徑的時候,Redirect會將網址重新轉到${this.props.match.url}/his上,我們來看看沒什麼用的示意圖,該Link的連結還是到/story,但跳過去後會進入Redirect中被轉址到/his
https://ithelp.ithome.com.tw/upload/images/20181013/20106935cl145Vcifg.jpg

基本用法如上,但是在Redirectto屬性中也能夠傳入物件,物件裡面有什麼呢?讓我們來看看:

<Redirect from={`${this.props.match.path}/story`} 
            to={{pathname:`${this.props.match.url}/his`
                ,search: "?hey=UCCU"
                ,state:{name:'Referrer'}}} />
  1. pathname:這個路徑就是上方的有效路徑,也就是要重新定向的網址。
  2. search:加在重定向的url後當作QueryString
  3. state:這個就厲害了,他能夠在傳到該路徑,而該路徑又進入某Route時,在class中使用this.props.location.state取得state的物件。

為了確認我們在His組件的render()中加入以下行:

class His extends React.Component {
    render() {
        console.log(this.props.location.state)
        return <p>這裡是歷史沿革</p>
    }
}

接著來看看跳轉後會發生什麼事吧!
https://ithelp.ithome.com.tw/upload/images/20181013/20106935tmwsQVIC0a.jpg

亮點有兩個地方,第一個是點擊品牌介紹後,重新定向的網址後會出現search的值,而在跑進組件時,也能使用this.props.location.statestate給印出,以下附上上方例子的程式碼和執行頁面。

Github程式碼連結
GitPage頁面連結

Umm...這樣執行起來Redirect感覺比Route強多了耶?不過其實不會啦!因為在Route中也可以使用params將參數傳到class中啊!所以其實不會差多少,只是Redirect是用state當作參數,我想只是要和一般的Route做出差別,在某些情況下能讓組件判斷到底是誰在呼叫他,並做出渲染不同的結果。

不過其實Route還有一個未提到的屬性render,他能做到的事情更加靈活,這裡先賣個關子,讓我們明天繼續看下去!


今天的文章到這裡結束!感謝各位大大的觀看,如果文章中有任何問題或是講解不清楚的地方,還麻煩留言告訴我,小弟會再進快修正或補充文章內容的!謝謝大家/images/emoticon/emoticon41.gif

參考文章:

  1. https://reacttraining.com/react-router/web/api/Switch
  2. https://reacttraining.com/react-router/web/api/Redirect

上一篇
[筆記][React]React網頁好朋友Router(2)-掌握match是成功的一半
下一篇
[筆記][React]React網頁好朋友Router(4)-搞懂Route的component、render和children
系列文
一步一腳印的React旅程30

尚未有邦友留言

立即登入留言