iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 8
0

在上一篇的程式碼中
出現了this.props.XXX這種長相的東西
這一篇就要來仔細的看看
究竟這是什麼神奇的東東囉

Props

props 的中文翻譯是道具
在這裡其實是一個非常像參數的概念
程式中我們常常透過參數讓函式可以拿到某些資料
props 就很像函式針對傳進來的參數寫的一個接收物件
只要透過 props
組件就可以取得所要使用的資料
但是 props 本身 不能直接改變 接收到的值
只能單純取出資料並放到對應位置渲染組件
這點需要特別注意!!

props 接收資料大致可以分成三種方式:

  1. 直接給 props 資料
  2. 預設 props 有資料
  3. 從狀態傳給 props 使用

接下來就逐個說明他們是怎麼個傳遞資料法囉~

直接給 props 資料

首先讓我們看看這段程式碼

// main.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.jsx';

ReactDOM.render(<App score = "100" />, document.getElementById('app'));

export default App;

這是 main.js 透過 ReactDOM 去渲染 App 這個組件到前端id為 app的地方
可以看到在App的組件裡面有一段score = "100"
這就是直接把 100 這個值透過命名成 score 傳入 App 這個組件裡面
接著在 App 組件內我們可以透過this.props.score取得這個傳入的值
this.props.score可以解讀成

這個組件(this)的道具(props)裡面的一個變數(這裡叫做score)的值

程式碼如下:

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            {this.props.score}
         </div>
      );
   }
}
export default App;

這段程式碼中在渲染組件時直接將所需要的值傳遞進去
讓組件可以透過 props 去取用
執行結果與產生出來的 html 程式碼如下:
https://ithelp.ithome.com.tw/upload/images/20171227/20107674E4brChQNyd.png
傳遞並不局限於只能傳一個
也可以給予複數個名稱以及值
只要在使用的時候this.props.指定的名稱
就能夠拿到對應的資料了

以上就是直接給props資料的方式

預設 props 有資料

有些時候值在一開始就已經決定了
那就不一定要在渲染的時候給
可以直接設定組件的defaultProps

import React from 'react';

class App extends React.Component {
   render() {
      return (
         <div>
            <p>{this.props.animal1}</p>
            <p>{this.props.animal2}</p>
         </div>
      );
   }
}
App.defaultProps = {
   animal1: "Dogdog",
   animal2: "Catcat"
}
export default App;

這段程式碼裡面的App.defaultProps就是預設的方式
將資料命名後指給組件底下的defaultProps
那麼渲染的時候就可以直接使用這些資料了
執行結果與 html 程式碼:
https://ithelp.ithome.com.tw/upload/images/20171227/20107674GqzwgLbPLg.png

從狀態傳給 props 使用

前面有提到
props 不能改變接收到的值
那如果組件的值必須要被改變的時候怎麼辦呢?
這時候就要透過狀態(state)來傳遞資料給 props 了
和 props 不同
state 是可以透過setState函式來改變資料的
所以如果是從 state 傳過來
在 state 發生改變時
render函式就會同步更新到取用這些狀態的組件了
用法如下:

import React from 'react';

class App extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
         name: "RayRay"
      }
   }
   render() {
      return (
         <div>
            <Content id = {this.state.name}/>
         </div>
      );
   }
}
class Content extends React.Component {
   render() {
      return (
        <h1>{this.props.id}</h1>
      );
   }
}
export default App;

眼尖的大家一定覺得這種用法好像在哪裡看過
沒錯
在上一篇產生表格的那段程式碼裡面
每一列資料就是用這個方法去取得狀態並渲染出來的
這邊比較要注意的地方是
在下層組件中透過 props 取得資料的時候
用來識別的名稱是 渲染下層組件時自己定義的名稱
也就是說在這段程式碼裡面
必須使用this.props.id才能取得資料
要是寫成this.props.name
那 Content 這個組件就拿不到資料了喔!

執行結果與產生的html程式碼:
https://ithelp.ithome.com.tw/upload/images/20171227/201076740Z6n1nfL41.png

介紹完 props 三種不同的接收資料方式
最後要說的是一個系統變大之後
提升後續維護程式效率的一個東東

Props Validation

等到系統變得龐大程式變得複雜
一堆資料傳來傳去的時候
很容易發生給錯資料這種事情
為了讓我們維護的時候可以快速發現這個小失誤
props 有一個叫做App.propTypes的東西
他的寫法和給予 props 初始值的方式一樣
只是裡面寫的東西是每一個 props 裡面的名稱對應的資料型態

App.propTypes = {
   name: PropTypes.string,
   propArray: PropTypes.array.isRequired,
   propBool: PropTypes.bool.isRequired,
   propFunc: PropTypes.func,
   propNumber: PropTypes.number,
   propString: PropTypes.string,
}

這段程式碼是在設定每一個props中的名稱對應到的值的資料型態
寫法是PropTypes.資料型態(.isRequire)
isRequire是代表這個資料必須要有對應值
可以視需求在對應的資料名稱後加上
如果給予的值和要求的資料型態不相符
網頁會給予一個警告提醒型態不符
可以大大提升除錯(debug)時的速度和效率喔!!


參考資料

  1. tutorialspoint-ReactJS Tutorial
  2. React - Functional and Class Components

>>> 隊友任意門 <<<


Day8 end
by 瑞Ray (,,・ω・,,)


上一篇
【Day07】 你的狀態還好嗎 - State
下一篇
【Day09】 組件的一生 - Lifecycle
系列文
激戰 ReactJS 30天31

尚未有邦友留言

立即登入留言