React Redux: 从文档看源码 - Connect东西类篇(2)

注:这篇文章只是解说React Redux这一层,并不包括Redux部份。Redux有设计去进修,等今后进修了Redux源码今后再做剖析
注:代码基于如今(2016.12.29)React Redux的最新版本(5.0.1)

Connect东西类篇(1)

Connect东西类篇(2)

verifySubselectors.js

这里有四个参数:

  1. mapStateToProps, mapDispatchToProps, mergeProps都是经由mapDispatchToProps, mapStateToProps, mergeProps封装过的

  2. displayName是option内里传入的
    重要做的是搜检传入的mapStateToProps,mapDispatchToProps,mergeProps是不是存在,由于这里的对象是经由几个map要领封装过的,所以不存在就申明开辟传入的值是毛病的。同时搜检是不是有dependsOnOwnProps这个属性,假如没有给一个warning.

import warning from '../utils/warning'

function verify(selector, methodName, displayName) {
  if (!selector) {
    throw new Error(`Unexpected value for ${methodName} in ${displayName}.`)

  } else if (methodName === 'mapStateToProps' || methodName === 'mapDispatchToProps') { //只搜检mapStateToProps和mapDispatchToProps, 由于mergeProps要领不须要
    if (!selector.hasOwnProperty('dependsOnOwnProps')) {
      warning(
        `The selector for ${methodName} of ${displayName} did not specify a value for dependsOnOwnProps.`
      )
    }
  }
}

export default function verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps, displayName) {
  verify(mapStateToProps, 'mapStateToProps', displayName)
  verify(mapDispatchToProps, 'mapDispatchToProps', displayName)
  verify(mergeProps, 'mergeProps', displayName)
}

selectorFactory.js

这里重要担任猎取处置惩罚过的mapStateToProps, mapDispatchToProps, mergeProps和传入的options,来举行props的兼并,末了返回兼并后的效果。个中,当pure为true的时刻,会对props举行存储,便于下一次比较,假如经由过程比较两个雷同,那末就不转变props对象,削减不必要的re-render。

在connectAdvanced.js内里看到这么一段解释:

selectoryFactory要领返回的是一个function,这个function的作用是依据Redux Store state, props和dispatch盘算新的props. 在connectAdvanced中会供应dispatch给selectorFactory,以便selectorFactory能够对actionCreator举行绑定。connectAdvanced猎取的option设置会直接被传给selectorFactory,个中就包括了displayName和wrappedComponent(实在另有一些对照的要领在内里)。

selectorFactory担任纪录一切的状况(props, store state, dispatch, mergedProps),以便在部份状况发作转变,而不影响组件衬着的时刻,能够防止不必要的衬着。

finalPropsSelectorFactory

export default function finalPropsSelectorFactory(dispatch, {
  initMapStateToProps,
  initMapDispatchToProps,
  initMergeProps,
  ...options
}) {
  const mapStateToProps = initMapStateToProps(dispatch, options)
  const mapDispatchToProps = initMapDispatchToProps(dispatch, options)
  const mergeProps = initMergeProps(dispatch, options)

  if (process.env.NODE_ENV !== 'production') {
    verifySubselectors(mapStateToProps, mapDispatchToProps, mergeProps, options.displayName)
  }

  const selectorFactory = options.pure
    ? pureFinalPropsSelectorFactory
    : impureFinalPropsSelectorFactory

  return selectorFactory(
    mapStateToProps,
    mapDispatchToProps,
    mergeProps,
    dispatch,
    options
  )
}

这里只是给mapStateToProps, mapDispatchToProps, mergeProps传入dispatch和options对象,然后依据pure的值传给差异的要领举行处置惩罚。

假如pure是true, 那末selectorFactory返回的selector会担任存储末了效果。假如效果没有发作转变,那末connectAdvanced的shouldComponentUpdate就会返回false。

假如pure是false, 那末selector永久会返回一个新的对象,同时shouldComponentUpdate永久都返回true

这个factory要领会返回一个function,吸收Redux Store和ownProps作为参数。作用是,每次store或ownProps发作转变今后,挪用这个返回的function,猎取更新后的终究props。

impureFinalPropsSelectorFactory

export function impureFinalPropsSelectorFactory(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps,
  dispatch
) {
  return function impureFinalPropsSelector(state, ownProps) {
    return mergeProps(
      mapStateToProps(state, ownProps),
      mapDispatchToProps(dispatch, ownProps),
      ownProps
    )
  }
}

依据pure即是false的状况,这里会永久返回一个新的对象。存粹的、不加任何推断的挪用mergeProps对几个props的构造举行兼并。

这里返回的值的花样是:(state, ownProps)=>final props

pureFinalPropsSelectorFactory

export function pureFinalPropsSelectorFactory(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps,
  dispatch,
  { areStatesEqual, areOwnPropsEqual, areStatePropsEqual }
) {
  let hasRunAtLeastOnce = false // 是不是是第一次挪用,第一次挪用不须要做是不是转变的搜检
  let state // 影象上一次的state
  let ownProps // 影象上一次的ownProps
  let stateProps // 影象mapStateToProps返回的props
  let dispatchProps // 影象mapDispatchToProps返回的props
  let mergedProps // 影象末了兼并后的效果

  // 第一次挪用的时刻,地道记着一切的效果
  function handleFirstCall(firstState, firstOwnProps) {
    state = firstState
    ownProps = firstOwnProps
    stateProps = mapStateToProps(state, ownProps)
    dispatchProps = mapDispatchToProps(dispatch, ownProps)
    mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
    hasRunAtLeastOnce = true
    return mergedProps
  }

  // 当两个都发作转变。。。
  function handleNewPropsAndNewState() {
    stateProps = mapStateToProps(state, ownProps) // ownProps发作了转变,一定须要挪用猎取新的props

    if (mapDispatchToProps.dependsOnOwnProps)
      dispatchProps = mapDispatchToProps(dispatch, ownProps)

    mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
    return mergedProps
  }

  // 假如只要父组件传入的props发作了转变,那末须要依据dependsOnOwnProps来举行更新
  function handleNewProps() {
    if (mapStateToProps.dependsOnOwnProps)
      stateProps = mapStateToProps(state, ownProps)

    if (mapDispatchToProps.dependsOnOwnProps)
      dispatchProps = mapDispatchToProps(dispatch, ownProps)

    // 由于ownProps发作了转变,所以不须要举行搜检,直接挪用mergeProps要领
    mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
    return mergedProps
  }

  // 假如只要Redux store state发作了转变,那末只用更新mapStateToProps的返回值,由于dispatchProps和Redux State无关
  function handleNewState() {
    const nextStateProps = mapStateToProps(state, ownProps)
    const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps)
    stateProps = nextStateProps
    
    if (statePropsChanged)
      mergedProps = mergeProps(stateProps, dispatchProps, ownProps)

    return mergedProps
  }

  // 除第一次挪用外,每次都须要对种种效果举行搜检,然后纪录必要的效果
  function handleSubsequentCalls(nextState, nextOwnProps) {
    const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps) // 搜检ownProps是不是发作转变
    const stateChanged = !areStatesEqual(nextState, state) // 搜检Redux store state是不是发作转变
    state = nextState
    ownProps = nextOwnProps

    // 依据转变的差异,挪用差异的要领。削减不必要的运算
    if (propsChanged && stateChanged) return handleNewPropsAndNewState()
    if (propsChanged) return handleNewProps()
    if (stateChanged) return handleNewState()
    return mergedProps
  }

  return function pureFinalPropsSelector(nextState, nextOwnProps) {
    return hasRunAtLeastOnce
      ? handleSubsequentCalls(nextState, nextOwnProps)
      : handleFirstCall(nextState, nextOwnProps)
  }
}

当pure即是true的时刻,须要做出种种搜检来剖断是不是须要挪用要领,来猎取新的props.

  1. 当Redux state发作转变,ownProps没变的时刻
    1) 由于mapDispatchToProps并没有基于Redux State,所以dispatchProps是须要举行更新的。2) 而mapStateToProps是基于Redux State的,所以须要挪用mapStateToProps要领也许”新的”stateProps。由于State发作转变,并不一定会形成返回效果的转变,所以须要依据搜检后的效果来剖断是不是挪用mergeProps要领。

  2. 当OwnProps发作转变,Redux State没有转变的时刻
    1) 由于mapDispatchToProps和mapStateToProps都能够基于ownProps,所以须要依据dependsOnOwnProps属性来搜检,推断是不是须要挪用要领举行更新。2) ownProps作为mergeProps的一个必要参数,所以不须要做任何推断,mergePorps必需被挪用

  3. 当Redux Store, OwnProps都发作了转变
    综合之前的两点,mapStateToProps必需挪用,mapDispatchToProps依据dependsOnOwnProps属性挪用,mergeProps必需挪用

一点总结:

  1. 在connect定义的时刻,平常只管运用pure:true的状况(默认值),由于在这类状况下,会对props举行差异搜检。假如没有转变,就不会去挪用connectAdvanced组件去更新。假如内部组件同时依据 父组件传入的propsRedux store的其他状况举行更新衬着,那末pure必需是false。

  2. option中的areStatesEqual(默认值为===),areOwnPropsEqual(默认值为shallowEqual), areStatePropsEqual(默认值为shallowEqual), areMergedPropsEqual(默认值为shallowEqual),能够依据须要来修正这几个参数,当pure为true的时刻,搜检更多不必要的re-render

    原文作者:Clark
    原文地址: https://segmentfault.com/a/1190000008022029
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞