iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 3
0
自我挑戰組

玩轉 React 從0到1系列 第 19

【Day 19】React 結合 Redux:react-redux 實作

  • 分享至 

  • xImage
  •  

實作之前

react-redux 套件

react-redux 是 Redux 作者封裝的一個第三方模組,它對 Redux 進行簡化提供額外的 API (像是Provider、connect等),那並不是一定要用其實也可以用 Redux 就好,接下來會說明一下 Redux 和 react-redux 流程上的差異,我們今天實作所使用的也是 react-redux,所以也先 npm install react-redux --save 裝好套件唷。

Redux 的流程: component -> dispatch(action) -> reducer -> subscribe -> getState -> component

react-redux 的流程: component -> actionCreator(data) -> reducer -> component

Provider

Provider 傳遞了 Store 到每個元件,讓所有元件都有辦法獲取 Store 裡的資料,以及 dispatch(action)

Provider 是對 Redux 中的 Store 的 subscribe, dispatch, getState 的一個集合,它接收了 Redux 創建的 store ,並根據 component 裡的 mapStateToProps 上要求將資料從 store 中取出,以 props 形式傳給 Component。

connect

connect 是用來連接 React Component 和 Redux Store 的,connect 最終會返回一個已經與 Redux Store 連接的 Component

connect 總共可以接收四個參數:mapStateToProps、mapDispatchToProps、mergeProps、options。

import { connect } from 'react-redux';
const VisibleComponent = connect(mapStateToProps, mapDispatchToProps,mergeProps, options)(ComponentName);

mapStateToProps(state, [ownProps])

mapStateToProps 就是將 Store 裡 State 的資料作為 Props 傳送到 Component 裡

mapStateToProps 接收兩個參數,State 指的是 Store 裡的 State,而 ownProps 代表的是當下Component 裡的 props,這個函數會去訂閱 Store 裡的 State,如果有變化就會執行這個函數;如果有傳入第二個參數,當本身的 props 有變化的時候也會觸發這個函數

const mapStateToProps = (state) => {
  return {
    storeListValue: state.storeListValue
  }
}

mapDispatchToProps(dispatch, [ownProps])

mapDispatchToProps 定義了哪些 Component 裡的操作應該被當作 Action 並傳給 Store

mapDispatchToProps 可以是一個函數也可以是 Object,如果是函數主要是在定義 Component 如何發出這個 Action,其實就是調用 dispatch 這個方法。

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    increase: (...args) => dispatch({ type: 'BeTriggeredAction'}),
  }
}

mergeProps(stateProps, dispatchProps, ownProps)

主要是將 mapStateToProps() 與 mapDispatchToProps() 返回的 props 跟自己本身的 props 合成新的 props 傳入 Component 內。

const mergeProps = () => {
  return Object.assign({}, ownProps, stateProps, dispatchProps)
}

開始實作

這裏將實作一個簡單的計算機,有 + - * 功能的為例子。

檔案位置 src/reducer.js

import React from 'react';
import { connect } from 'react-redux';

const initialValue = 300;

const increase = {
  type: '加'
}

const decrease = {
  type: '減'
}

const mutiplication = {
  type: '雙倍'
}

const reducer = (state = initialValue, action) => {
  switch (action.type) {
    case '加':
      return state += 1;
    case '減':
      return state -= 1;
    case '雙倍':
      return state *= 2;
    default:
      return state;
  }
}

export default reducer;

檔案位置 src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import reducer from './reducer';

const store = createStore(reducer);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

檔案位置 src/App.js

import React from 'react';
import { connect } from 'react-redux';

class App extends React.Component {
  render() {
    const { Increase, Decrease, Double } = this.props;
    return (
      <div className="App">
        <h2>當下數字為: {this.props.number}</h2>
        <button onClick={Increase}>增加</button>
        <button onClick={Decrease}>減少</button>
        <button onClick={Double}>雙倍</button>
      </div>
    )
  }
}
// 需要渲染什麼數據
function mapStateToProps(state) {
  return {
    number: state
  }
}
// 需要觸發什麼行為
function mapDispatchToProps(dispatch) {
  return {
    Increase: () => dispatch({ type: '加' }),
    Decrease: () => dispatch({ type: '減' }),
    Double: () => dispatch({ type: '雙倍' })
  }
}
export default App = connect(mapStateToProps, mapDispatchToProps)(App);

結論

  • 介紹了 react-redux
  • 實作 react-redux 的計數器

/images/emoticon/emoticon31.gif


上一篇
【Day 18】React 關於 Redux
下一篇
【Day 20】React 結合 Redux 與 React-Router
系列文
玩轉 React 從0到130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言