youngwind / blog

梁少峰的个人博客
4.66k stars 384 forks source link

redux精简代码之--抽象select函数和mapDispatchToProps函数 #10

Open youngwind opened 8 years ago

youngwind commented 8 years ago

前言

在redux项目中,我们常常使用select函数和mapDispatchToProps函数,前者用于从store中getState(),然后输入到组件的props中去,后者用于给函数自动绑定上dispatch,不必每次调用执行函数都写dispatch。

碰到的问题

因为项目只要稍微大一点就需要结合使用react-router和container的概念。比如我在某个项目中就有以下两个container。

// container index
const Index = React.createClass({

  render: function () {
    return (
        <div className="container">
          {this.props.children}
        </div>

    )
  }
});

const select = (state) => ({
  promotionPage: state.promotionPage.data,
  isFetching: state.promotionPage.isFetching,
  productData: state.productData,
  productIsFetching: state.productData.isFetching,

});

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(TemplateActions, dispatch)
});

module.exports = connect(select, mapDispatchToProps)(Index);
// container template
const Template = React.createClass({

  /**
   * 根据请求过来的数据合成区块
   * @param blocks {array} 区块数组
   * @returns {*} {JSX}
   */
  combineBlockList: function (blocks) {
    const _self = this;
    return blocks.map(function (block, index) {
      return (
          <div key={index}>
            <WapBlock block={block} type={_self.props.location.query.type}/>
          </div>
      )
    });
  },

  render: function () {
    const {promotionPage,isFetching,productDate, productIsFetching} = this.props;
      return (
          <div>
            {this.combineBlockList(promotionPage.blocks)}
          </div>
      )
  }
});

const select = (state) => ({
  promotionPage: state.promotionPage.data,
  isFetching: state.promotionPage.isFetching,
  productData: state.productData,
  productIsFetching: state.productData.isFetching,

});

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(TemplateActions, dispatch)
});

module.exports = connect(select, mapDispatchToProps)(Template);

从上面两个container可以看出,select和mapDispatchToProps都是重复的代码,可以也应该抽象出来。 所以我就定义了一个bindProps.js

// bindProps.js
/*
 *   created by liangshaofeng on 2015年12月18日
 *   抽象出每个container所需要的select和mapDispatchToProps
 */

import {bindActionCreators} from 'redux';
import TemplateActions from '../action/template.js';

const select = (state) => ({
  promotionPage: state.promotionPage.data,
  isFetching: state.promotionPage.isFetching,
  productData: state.productData,
  productIsFetching: state.productData.isFetching,
});

const mapDispatchToProps = (dispatch) => ({
  actions: bindActionCreators(TemplateActions, dispatch)
});

module.exports = {
  select,
  mapDispatchToProps
};

然后再两个container中分别import进去就可以了。😊