redux: redux以及中間件redux-saga思路的代碼實現模板

  • 入口文件
//app.js

//引入react-redux相關方法
import { Provider } from 'react-redux'
//引入redux相關方法
import { createStore, applyMiddleware } from 'redux';
//引入合併事後的reducer
import rootReducer from './reducers';

//引入中間件redux-saga
import createSagaMiddleware from 'redux-saga';

//引入saga的相關方法
import rootSaga from './saga';

//講reducer方法和中間件saga引入到store中
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));

sagaMiddleware.run(rootSaga);


export default class App extends Component {
  render() {
    //此處省略其餘業務代碼
    ....

    return (
      <Provider store={store}>
        //此處省略其餘業務代碼
        ....
      </Provider>
    );
  }
}


/**
 * Render the main compoent
 */
render(<App />, document.getElementById('app'));
  • 容器組件
//container.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';
//引入react-redux組件的connect方法
import { connect } from 'react-redux';

import ExampleComponent from './component';

import ExampleActions from './actions';

//此方法實現了傳入UI組件的props的items的監聽,一旦數據有更新,便會自動更新
const mapStateToProps = (state) => {
  return {
    //注意:此處因爲reducers處使用了combineReducers將多個reduce合併,每一個reducer中可能會有同名的state值
    //因此state.example.items中的example必定要加,否則會報錯     
    items: state.example.items
  }
};

//此方法實現了傳入UI組件dispach方法
const mapDispatchToProps = (dispatch) => {
  return {
    getItems: () => dispatch(ExampleActions.getItems())
  }
};

//經過redux中的connect方法將原來的簡單的展現組件變成高階組件
const ExampleContainer= connect(mapStateToProps, mapDispatchToProps)(ExampleComponent);

//將容器組件ExampleContainer暴露出來給view層使用
export default ExampleContainer;
  • 展現組件
//componment.js

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class ExampleComponent extends Component {
  static propTypes = {
    //經過PropTypes方法檢查容器組件經過connect傳進來的屬性和方法
    items: PropTypes.object,
    getItems: PropTypes.func,
    //此處省略其餘業務代碼
    ....

  };

  //在須要的地方調用觸發函數
  componentDidMount() {
    if (this.props.getItems) {
      this.props.getItems()
    }
  }

  render() {

    const {
      items,
      //此處省略其餘業務代碼
       ....
    } = this.props;

    //在須要的地方使用傳進來的數據
    Object.keys(items).map((index) => {
      let item = items[index];
      //此處省略其餘業務代碼
      ....
      );
    });

    return (
      //此處省略其餘業務代碼
      ....
    );

  }


}

export default ExampleComponent;
  • action
//actions.js

import { ITEMS_GET_FETCH } from './actionTypes'

class ExampleActions {

  getItems(searchs) {
    return {
      type: ITEMS_GET_FETCH,
    }
  }
}

//講實例化後的ExampleActions暴露給容器組件使用
export default new ExampleActions;
  • saga
//saga.js

import { ITEMS_GET, ITEMS_GET_FETCH} from './actionTypes'
//引入effects API的call, put, takeEvery方法
import {call, put, takeEvery} from 'redux-saga/effects';
//引入封裝fetch方法的cfetch
import {cfetch, checkStatus, parseJSON} from '../../utils/cfetch';

//worker saga這裏實際上是有接收參數的 這個參數action就是redux執行dispatch方法中的參數
function* fetchGetItems(){
  
  try {
    const p =function () {
      return cfetch('/clients/name')
        .then(checkStatus)
        .then(parseJSON)
        .then(function (json) {
          return json
        });
    };
    //執行異步函數,此時本次的worker saga事件會暫停直到異步函數執行完成
    //當前是一個Promise,在該Promise的狀態從pending轉到resolve或reject以前,當前worker saga變出於暫停狀態
    //若狀態爲resolve,則將帶着返回值繼續執行
    //若狀態爲reject,則將在Generator中拋出一個錯誤,被catch捕獲
    const data = yield call(p);
    
    //指示中間件發起一個action到Store層,做用和 redux 中的 dispatch相同, 這個 effect 是非阻塞型的
    //會異步執行,整個Generator執行完畢
    yield put({type: ITEMS_GET, clients: Object.assign({},data)});
  } catch (e) {
    console.log(e);
  }
}

//watcher saga
function* rootSaga() {
  //監聽來自action層的觸發,攔截到後調用對應的worker saga(本例子中的fetchGetItems)
  //takeEvery容許多個worker saga實例同時啓動
  yield takeEvery(ITEMS_GET_FETCH, fetchGetItems);
}

export default rootSaga;
  • reducer
import { ITEMS_GET } from './actionTypes'

//定義數據的初始值
const initialState = {
  items: {},
};

const exampleReducer = (state = initialState, action) => {
  switch (action.type) {
    //sage層攔截到action的觸發,進行一系列異步操做而後觸發reducer以下,並將action傳進來
    //這裏的state不是覆蓋,而是將原來的state和更新的內容合併生成新的state,而後交給store處理
    case ITEMS_GET:
      return {...state, items: action.items};

    default:
      return state;
  }
};

export default exampleReducer;
相關文章
相關標籤/搜索