iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 20
4
Modern Web

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

[筆記][React]React網頁好朋友Router(4)-搞懂Route的component、render和children

  • 分享至 

  • xImage
  •  

Hi!大家好啊!想不到又重回最初的Route篇了吧!不過其實一開始也根本沒有說到他過XD,連他的小跟班match都提過了,就是沒有好好解釋過Route這個組件,所以今天就來解掉昨天賣的關子吧!


component

經過前幾天的洗禮,大家都知道Route可以在url符合path的時候,將該Route內指定的component給渲染出來,並利用對對應網址目錄的位置傳入param對吧?最簡單的做法就像下方這樣子:

<Link to="/hello/GQSM">用Component渲染組件</Link>

<Route path="/hello/:userName" component={Hello}>

class Hello extends React.Component{
    render(){
        return <h1>Hello!{this.props.match.params.userName}!</h1>
    }
}

第一行設定連結,將網址列變成to的值。
第二行設定進入Routepath,符合的話渲染Hello組件,並用:userName來接參數。
第三行就是Hello組件的class,並藉由this.props.match中的params來取得參數userName的值。

結果會如下(GitHub連結會在本文章的最後一起提供!):
https://ithelp.ithome.com.tw/upload/images/20181014/20106935w1dEvHNEBe.png

render

咦?大哥你484打文章打到昏頭了?我們現在在講Route不是class組件哦!

沒錯!

Route中也有一個render屬性,我們能夠用inline(行內函式)的方式寫一個function,讓該functionclass一樣建立一個的組件渲染,畢竟class的本體本來就是function對吧?讓我們來看看以下範例吧!

<Link to="/hey/GQSM">用render渲染組件</Link>

<Route path="/hey/:userName" 
        render={props => <h1>Hey!{props.match.params.userName}</h1>} />

第一行的Link一樣設定了進入點。
第二行的Route少了渲染組件的component,取而代之的是將一個匿名函數傳入render中,另外為了讀到match,記得要將props傳入render的匿名函式中。

結果如下:
https://ithelp.ithome.com.tw/upload/images/20181014/20106935YhqZNgn9aM.png

rendercomponent有什麼不一樣嗎?

據官方的說法,如果在兩者都傳入匿名函數的狀況下,compnent會使用React.createElement(應該還記得他吧XD,忘記的話可以到([筆記][React]踏出認識React的第一步回憶一下),建立一個組件出來,如果是render的話會直接執行匿名函數,並渲染該函數return的組件。

簡單來說,當把匿名函數放進component的時候,每一次都會重新移除該Route渲染的組件,再進行React.createElement新增,所以當我們要直接在Route中使用inline的話,render會是最好的選擇,只是要注意的是之前也有提到說,只有用class才能擁有生命週期,所以在使用時還是要看狀況取捨!

但是千萬要記得,component的執行權會比render還高,所以別把兩個寫進同一個Route中,否則他還是會以component指定的組件為主。

children

這個渲染方式很有趣,children的使用方法是給他一個能夠回傳組件的匿名函式,而不論目前url的路徑或path的設定為何,children都會觸發,但是只要url符合path的時候Route還是會在建構組件的時候傳入match,而我們在依照match的資料去判斷需要渲染怎麼樣的組件。

官方的例子使用在渲染不同樣式的Link,首先我們新增一個class

class CusLink extends React.Component{
    render(){
        return(
            <Route /*(1)*/ path={this.props.to} 
                   /*(2)*/ children={props=>{
                                console.log(props.match)
                                //(3)
                                return(
                                    <li>
                                        {props.match ? ">" : ""}
                                        <Link to={this.props.to}>{this.props.name}</Link>
                                    </li>)
            }} />
        )
    }
}

上方的class分成三個部分解釋一下:

  1. 設定path,雖然children不論如何都會渲染,但是只有在url符合path時才會產生match,不然會是null,為了看變化,我們有在匿名函式中設定console.log(props.match)等等可以觀察到。
  2. children傳入一個匿名函式,記得要將props傳入匿名函式,因為match會出現在props中。
  3. 假設先不管{props.match ? ">" : ""},我們要輸出的組件就像上方的例子中的Link
    <Link to="/hey/GQSM">用render渲染組件</Link>
    
    那當我們在使用組件時就可以以下方設定渲染出一樣的組件:
    <CusLink to="/hey/GQSM" name="用render渲染組件" />
    
    因為toname分別會傳到匿名函式中propstoname,所以這裡只是把資料放在對應的位置而已。
    接下來剛剛不管的那一個{props.match ? ">" : ""},因為第一點有說path符合match才會有值,所以我們利用這一行來判斷,如果現在的畫面是由該Route渲染的話,就顯示一個>在連結名稱前面。

沒問題後!就可以來使用它了!既然有了連結,就直接把上方兩個例子給結合起來吧!

<div>
    <ul>
        <CusLink to="/hello/GQSM" name="用component渲染組件" />
        <CusLink to="/hey/GQSM" name="用render渲染組件" />
    </ul>
    <hr />
    <Route path="/hello/:userName" component={Hello} />
    <Route path="/hey/:userName" render={props => <h1>Hey!{props.match.params.userName}</h1>} />
</div>

結果會如下:
https://ithelp.ithome.com.tw/upload/images/20181014/20106935fTaNRIduma.jpg

  1. 首先可以看到兩個連結不論目前的urlRoutepath設定為何,兩個Link都會透過Route渲染出來。
  2. 左邊那張圖因為選擇了用component渲染組件,所以改變了url,而這時候url就符合了Route設定的path,因此會將match帶入值傳進匿名函式中,從下方綠色框框的地方可以看到match的值。
  3. 然後進入程式中就會經過{props.match ? ">" : ""}不是null的話就在Link前加個>,所以可以看到左邊的網址是/hello/GQSM符合Routepath,因此會出現>,當點了另一個後觸發Linkto改變網址後就,換另一個符合Route符合出現>

所有的組件都環環相扣的感覺很有趣,只要理解RouterLinkRoute的運作原理就會發現有一定的規律在,想發現這個規律可以多下console.log感受Router的執行,最後附上本次範例最後的Github連結,相信一路和我一起走了20天來的各位大家一定不難看懂:
GitHub程式目錄連結
上方例子的GitPage頁面連結

今天的例子還滿適合第二十篇的XD,算是一個門檻,因為不只說明了Route的三種渲染方法,還複習了之前React的組件基本用法,如果在這篇有點苦手可能要到前幾天回憶一下了XD,不過主要是因為renderchildren都是傳入匿名函式產生組件,對於之前習慣用class的我們就覺得很陌生,要去思考把class轉換成匿名函式會是什麼樣子!


最後還是感謝各位大大的觀看,如果文章中有任何不清楚或是有問題的地方,還麻煩大家留言告訴我,小弟會在盡快修正或調整文章內容的!謝謝大家/images/emoticon/emoticon41.gif

參考文章:

  1. https://reacttraining.com/react-router/web/example/custom-link
  2. https://reacttraining.com/react-router/web/api/Route/route-render-methods
  3. https://medium.com/frochu/viscovery-%E5%A6%82%E4%BD%95%E5%BE%9Ereact-router-v2-%E8%BD%89%E6%8F%9B%E8%87%B3v4-ebcb0e418a8d

上一篇
[筆記][React]React網頁好朋友Router(3)-Switch和轉址王Redirect
下一篇
[筆記][React]來做個作品吧!待辦事項「todolist」篇(1)-用React-Router做選單
系列文
一步一腳印的React旅程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言