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;

相关推荐