react-redux 源码解读之connect的mapDispatchToProps

5 篇文章 0 订阅
5 篇文章 0 订阅


connect对于mapDispatchToProps的处理跟mapStateToProps的处理流程是一样的,只有一点点差别,理解mapDispatchToProps时,可以结合mapStateToProps来理解。

以这样写法的mapDispatchToProps为例讨论

const faActionCreators = {
    abc:aaa=>{
        return {
            type:'ADD',
            id:num++,
            text:aaa,
        }
    },
    qqw:aaa=>({
        type:'TYY',
        id:num++,
        text:aaa,
    }),
    noa:aaa=>({
        type:'nono',
        id:num++,
        text:aaa,
    })
}
const mapDispatchToProps = faActionCreators;

在connectAdvanced.js的Connect组件中:
constructor内,定义了
this.initSelector();
从而会执行一次
const sourceSelector = selectorFactory(this.store.dispatch, selectorFactoryOptions)
而且在Connect组件中,只在此时执行一次selectorFactory,以后都不会执行。
selectorFactory()
就是执行
selectorFactory.js 的 finalPropsSelectorFactory()
从而执行一次
const mapDispatchToProps = initMapDispatchToProps(dispatch, options)

initMapDispatchToProps其实就是
wrapMapToProps.js的initConstantSelector;

组件在整个装载更新销毁过程当中只会执行一次 selectorFactory;因此只会执行一次finalPropsSelectorFactory(),因此只会执行一次initConstantSelector();

//initConstantSelector方法:
return function initConstantSelector(dispatch, options) {
    const constant = getConstant(dispatch, options)
    function constantSelector() { return constant }
    constantSelector.dependsOnOwnProps = false
    return constantSelector
  }

getConstant方法为:

//getConstant方法
dispatch => bindActionCreators(mapDispatchToProps, dispatch)

const mapDispatchToProps = initMapDispatchToProps(dispatch, options)

这里的mapDispatchToProps其实就是函数 constantSelector,从代码看,此函数不做任何事情,它是一个闭包函数,只是单纯从initMapDispatchToProps母函数中取数据,

而constant其实就是包装好的mapDispatchToProps:
{abc: ƒ, qqw: ƒ, noa: ƒ}

在selectorFactory.js中
dispatchProps = mapDispatchToProps(dispatch, ownProps)
相当于
dispatchProps = constantSelector(dispatch, ownProps)
可以看出dispatch, ownProps这两个参数是多余传递的。

执行selectorFactory.js中的 dispatchProps = mapDispatchToProps(dispatch, ownProps),并没有做任何事情,只是单纯获取已经在组件装载时已经包装好的mapDispatchToProps。
由于initConstantSelector从始至终只执行一次,所以,对于外层定义的mapDispatchToProps包装,只进行一次。

initConstantSelector与bindActionCreator

//initConstantSelector方法:
return function initConstantSelector(dispatch, options) {
   const constant = getConstant(dispatch, options)
   function constantSelector() { return constant }
   constantSelector.dependsOnOwnProps = false
   return constantSelector
 }

从代码看,initConstantSelector做了两件事:
1、返回一个constantSelector闭包函数;
2、执行getConstant(dispatch, options)获得constant,其目的就是存储好给闭包函数constantSelector使用

getConstant方法为:

//getConstant方法
dispatch => bindActionCreators(mapDispatchToProps, dispatch)

本文示例中,
actionCreators = faActionCreators;

export default function bindActionCreators(actionCreators, dispatch) {
  const keys = Object.keys(actionCreators)
  const boundActionCreators = {}
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    const actionCreator = actionCreators[key]
    if (typeof actionCreator === 'function') {
      boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
    }
  }
  return boundActionCreators
}

本文示例中,
actionCreator = aaa=>{
        return {
            type:'ADD',
            id:num++,
            text:aaa,
        }
    };
    
function bindActionCreator(actionCreator, dispatch) {
  return function() {
  //很妙的一个用法,通过apply与arguments,父函数可以达到最轻松自由灵活的使用子函数actionCreator
  // 最终外层发送dispatch时,都会断点进入到这里
    return dispatch(actionCreator.apply(this, arguments))
  }
}

mapDispatchToProps小结

mapDispatchToProps的包装只会在组件装载时,在构造函数中包装一次,以后直至组件销毁,不会再做包装的工作。

在在selectorFactory.js中
dispatchProps = mapDispatchToProps(dispatch, ownProps)并没有做任何事情,只是单纯获取已经在组件装载时已经包装好的mapDispatchToProps;
因为组件更新的时候,会执行this.selector.run(this.props),根据条件不同,可能会执行到 dispatchProps = mapDispatchToProps(dispatch, ownProps),就算这个代码执行了,也不会再次包装mapDispatchToProps,而只是简单的取数据而已。

mapDispatchToProps被包装后,最终的模样是什么,包装成的模样其实就是bindActionCreator源码写的(上文已经提到),直接给出包装后最终模样:

const mapDispatchToProps = (dispatch)=>{
  return {
    abc:aaa=>{
      dispatch({
        type:'ADD',
        id:num++,
        text:aaa,
      })
    }}

如果好奇,可以在bindActionCreator源码断点查看。

mapDispatchToProps 与 mapStateToProps的不同

组件更新,会执行this.selector.run(this.props);
会触发selectorFactory.js中都会执行
mapDispatchToProps(dispatch, ownProps)
mapStateToProps(state, ownProps)
但是只有组件装载过程中,第一次运行this.selector.run,才会执行同时执行
dispatchProps = mapDispatchToProps(dispatch, ownProps) (handleFirstCall方法)
nextStateProps =mapStateToProps(state, ownProps)
这一次执行获得的dispatchProps将会被闭包保存,供以后每次this.selector.run后使用;
以后每次执行this.selector.run,基本上可以认为不再执行dispatchProps = mapDispatchToProps(dispatch, ownProps) ;
而只是从第一次存储好的闭包的上下文取dispatchProps,
但以后每次执行this.selector.run都会执行nextStateProps =mapStateToProps(state, ownProps),然后更新组件都nextStateProps;

所以组件在运行当中,dispatchProps始终是相同都,nextStateProps只要有更新是动态变化都。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值