iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

玩轉 React 從0到1系列 第 13

【Day 13】關於 React 的 state, props 與 super

  • 分享至 

  • xImage
  •  

前言

在寫 React 的時候,會發現一個元件通常是通過刷新資料狀態來改變它的UI,而 React 元件有兩種資料載體,分別是 state 跟 props

State可以被稱作是元件中的內部狀態 (local state)
Props則是運用在元件間互相傳遞資料(通常是父元件到子元件)

state 與 setState

這裏會實作一個計數器,利用 state 與 setState 實作,一開使先在 constructor 分別宣告:

  1. super() ,這是為了使用 this 去取得實體化物件
  2. 一個名為 count 的 state 初始值為 0
  3. 一個 function 名為 onClickButton,可以試試不用bind這時候會噴錯,原因是因為裡面的this會呈現undefined的狀態,無法抓到 ClickCounter(詳細原因可以往前翻有一天是專門講 this 的)

在 onClickButton 的內容裡,運用了 setState 去不斷更新 count 這個的 state 值,當 button.onClick (按鈕被點擊)這件事發生的時候。

檔案位置:src/ClickCounter.js,以下為程式碼:

import React from 'react';

export default class ClickCounter extends React.Component {
  constructor() {
    super();
    this.state = { count: 0 };
    this.onClickButton = this.onClickButton.bind(this);
  }

  onClickButton() {
    this.setState({ count: this.state.count + 1 });
  }

  render() {
    return (
      <div>
        <button onClick={this.onClickButton}>Click Me</button>
        <div>
          Click Count: {this.state.count}
        </div>
      </div>
    )
  }
}

這邊 src/index.js 的工作就是負責渲染所有有引用到的元件到頁面上,而 document.getElementById('root')裡面所指的root是public資料夾中index.html檔案裡的<div id="root"></div>

檔案位置:src/index.js,以下為程式碼:

import React from 'react';
import ReactDOM from 'react-dom';
import ClickCounter from './ClickCounter';

ReactDOM.render(
  <ClickCounter />,
  document.getElementById('root')
);

props

如何給 prop 值

從父元件看 prop 使用:

<SampleButton id="sample" onClick={onButtonClick} style={{color: 'green'}}/>

這裏的例子是使用了 SampleButton 的元件,React 的 prop 可以支持類型除了字串還可以是 Javascript 支持的數據類型,當 prop 不是字串時在 JSX 中要用 {},所以像是 style 有兩層{},外層代表 JSX 的語法,裡面那層則代表是常量。

這裏是實作如何從父元件(CounterPanel)傳值到子元件(Counter),每個 Counter 元件都用了 name 和 initValue 兩個 prop,而這兩個 prop 分別給 Counter 名稱跟初始值

檔案位置:src/CounterPanel.js,以下為程式碼:

import React from 'react';
import Counter from './Counter';

export defualt class CounterPanel extends React.Component {
  render() {
    return (
      <div>
        <Counter name="First" initValue={0} />
        <Counter name="Second" initValue={20} />
      </div>
    )
  }
}

如何讀取 prop 值

這裏是從子元件的角度去看,如果子元件要定義自己的構造函數,一定要調用 super(props)也就是繼承了React.Component的構造函數,以 ES6 來說會先創建父元件的 this,然後再用子元件的構造函數修改 this 成為自己的;在繼承父元件後,宣告一個名為 count 的 state 初始值為 父元件傳遞過來的 initValue 或是(如果不存在)為0,以及兩個方法 onClickIncrementButton 與 onClickDecrementButton

檔案位置:src/Counter.js,以下為程式碼:

import React from 'react';

export default class Counter extends React.Component {
  constructor(props) {
    super(props);
    
    this.state = {
      count: props.initValue || 0,
    }

    this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
    this.onClickDecrementButton = this.onClickDecrementButton.bind(this);
  }

  onClickIncrementButton() {
    this.setState({ count: this.state.count + 1 })
  }

  onClickDecrementButton() {
    this.setState({ count: this.state.count - 1 })
  }

  render() {
    const {name} = this.props;

    return (
      <div>
        <button onClick={this.onClickIncrementButton}>+</button>
        <button onClick={this.onClickDecrementButton}>-</button>
        <span>{name} count: {this.state.count}</span>
      </div>
    )
  }
}

在 props 的範例中需更改,檔案位置:src/index.js,以下為程式碼:

import React from 'react';
import ReactDOM from 'react-dom';
import CounterPanel from './CounterPanel';

ReactDOM.render(
  <CounterPanel />,
  document.getElementById('root')
);

propTypes

在 ES6 定義元件中,可以透過增加元件的propTypes來定義 prop的格式,在運行檢查時,就可以根據propTypes判斷父元件是否正確使用了此元件的屬性。

增加 Counter 元件對 propTypes 的定義:

Counter.propTypes = {
  name: PropTypes.string.isRequied,
  initValue: PropTypes.number,
}

定義 propsType可以避免運用時犯錯,但在發布的時候可以使用 babel-react-optimize 消除 propTypes

結論

  • 介紹了 state, setState
  • 介紹了 prop
  • 介紹了 super

/images/emoticon/emoticon37.gif


上一篇
【Day 12】React 基礎安裝
下一篇
【Day 14】React 關於 JSX
系列文
玩轉 React 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言