react-redux源码解析

2,792 阅读17分钟

react-redux源码解析

react-redux作为大型react应用中链接react和redux的链接库,在很多reat项目中广泛应用。作为开发者的同学们了解reac-redux的原理和源码对我们的能力提升具有一定的帮助,所谓知其然知其所以然。

预备知识

react context

react 高阶组件(HOC)

react-redux(建议不知道connectAdvanced API,connectd的四个参数不是特别熟的同学先去简单过一下)

准备工作

老规矩github 找到 react-redux, clone master

  本文版本: 6.0.0-beta.3

当然你也可以选择看笔者的gitHub项目, 其中包含redux和react-redux的源码及详细的注释

开始撸码

打开项目之后,其他的不多说了,我们直接看src里面的核心代码,从index.js 开始(哦, 这里插一嘴,react-redux是基于react和redux实现的,可以看一下package.json里面的peerDependencies)

一如既往的简单, 暴露出的Provider, connectAdvanced, connect 都有对应的api, 我们先来看看Provider的实现。

Provider实现

我们先想一想reac-redux都干了什么,简单来说用 < Provider >< /Provider>包装了根组件, 把 store 作为 props 传递到每一个被 connect() 包装的组件,其中state to props的计算过程做了优化。 react本身倡导props的自上而下单项传递,但是也提供context支持跨层级传递,到这里,聪明的你是不是联想到了provider与context有关呢,直接看👀源码相关注释以添加

建议先看Provider.propTypes提供了那些props -> constructor -> render -> 声明周期钩子方法 -> 总结

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { ReactReduxContext } from './Context'

class Provider extends Component {
  constructor(props) {
    super(props)

    // 获取store
    const { store } = props

    // 初始化state, storeState为初始的redux state
    this.state = {
      storeState: store.getState(),
      // 保存init store
      store
    }
  }

  componentDidMount() {
    // 文件收索_isMounted, 共三处, componentWillUnmount中赋值为false
    // 先假设为标记componentDidMount -> componentWillUnmount中
    this._isMounted = true
    // 来看下subscribe
    this.subscribe()
  }

  componentWillUnmount() {
    // 取消监听subscribe
    if (this.unsubscribe) this.unsubscribe()
    // 生命周期结束this._isMounted 赋值为false =>_isMounted假设成立✅
    this._isMounted = false
  }

  componentDidUpdate(prevProps) {
    // 如果更新之后,store的引用发生变化
    if (this.props.store !== prevProps.store) {
      // 如果存在监听则取消
      if (this.unsubscribe) this.unsubscribe()
      // 更新storeState
      this.subscribe()
    }
    /*
    * 在我的理解中redux的store应该是不变的,主要就是为了提供"全局变量state"
    *   既然redux作者这样写,我们来思考一下为什么
    *   一般store应该是这样 let store = createStore(rootReducer, initState,  applyMiddleware(xxx));
    *   this.props.store !== prevProps.store说明全局的store发生了变化。既createStore方法的重新调用,
    *   阅读过redux源码的同学应该知道, 既然是新的createStore, "全局的state"会发生变化,不再是之前的内存空间
    *   所有这里再次调用subscribe更新state里面的storeState
    * 
    * * */

  }

  // 使用store.subscribe方法,保证storeState的最新
  subscribe() {
    const { store } = this.props
    // 监听subscribe
    this.unsubscribe = store.subscribe(() => {
     // 获取最新的state赋值给newStoreState
      const newStoreState = store.getState()
      // 不在本次生命周期中return
      if (!this._isMounted) {
        return
      }

      this.setState(providerState => {
        // If the value is the same, skip the unnecessary state update.
        // 如果state是相同的引用, 直接跳过state的更新
        if (providerState.storeState === newStoreState) {
          return null
        }

        // 更新当前storeState
        return { storeState: newStoreState }
      })
    })
    
    const postMountStoreState = store.getState()
    if (postMountStoreState !== this.state.storeState) {
      this.setState({ storeState: postMountStoreState })
    }
  }

  render() {
    // ReactReduxContext为默认context, 点过去看一下默认值。 看 -> context.js文件,createContext参数是null
    const Context = this.props.context || ReactReduxContext

    // value 为this.state
    return (
      <Context.Provider value={this.state}>
        {this.props.children}
      </Context.Provider>
    )
  }
}

Provider.propTypes = {
  // 接受store做为props, 并规定store object中的必要方法,既redux createStore的返回对象
  store: PropTypes.shape({
    subscribe: PropTypes.func.isRequired,
    dispatch: PropTypes.func.isRequired,
    getState: PropTypes.func.isRequired
  }),
  // 接收自定义context
  context: PropTypes.object,
  // children, 通常为根容器<app />
  children: PropTypes.any
}

export default Provider

/**
 *  provider总结
 * 
 *  provider是react-redux提供是react应用的入口组件, 一般为顶层组件<Provider store={store}><App /></Provider>
 *  使用react的context传递store, 老版本的provider用的getChildContext方法, 随着react context的api改变,生产者消费者模式的新api尤然而生,因此
 *  provider的源码已经重构, 提供的context为{ store, storeState: state},state保存为最新
 * 
 * * */

Context.js 提供全局的初始化ReactReduxContext

  import React from 'react'

// defaultValue 为 null
export const ReactReduxContext = React.createContext(null)

// export出来,以便提供给provider和consumer使用
export default ReactReduxContext

connect 实现

先回顾一下connect的使用形式:

connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])(<Xxx / >)

这里还要了解一下connectAdvanced(selectorFactory, [connectOptions])方法,它是一个将 React 组件连接到 Redux store 的函数。这个函数是 connect() 的基础。

由于connect方法内引用文件,function及function的嵌套比较多,如果看官老爷不想过于在意细节,可以直接看一下connect总结

开始看connect源码 -> connect.js,简单看看结构和引用了哪些东西 ->然后我们从export default开始->遇到调用的function再去具体看实现了哪些功能

connect.js

/**
 *  先回顾一下connect的参数connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
 *  作用:连接 React 组件与 Redux store
 *  mapDispatchToProps(dispatch, [ownProps])
 * 
 *  react-redux 暴露的api, connectAdvanced(selectorFactory, [connectOptions])
 *  连接react组件和redux的store, 这个参数是connect的基础
*/
import connectAdvanced from '../components/connectAdvanced'
import shallowEqual from '../utils/shallowEqual'
import defaultMapDispatchToPropsFactories from './mapDispatchToProps'
// mapStateToProps(state, ownProps)
// 只要 Redux store 发生改变,mapStateToProps 函数就会被调用, 
// 或者如果有ownProps参数组件接收到新的props,mapStateToProps同样会被调用
import defaultMapStateToPropsFactories from './mapStateToProps'
// mapStateToProps() 与 mapDispatchToProps() 的执行结果和组件自身的 props 将传入到这个回调函数中
import defaultMergePropsFactories from './mergeProps'
// 定制 connector 如 pure = true 等等等...
import defaultSelectorFactory from './selectorFactory'

/**
 *
 * 这里先以mapStatetoProps为例子, 其他的同理,简单了解后续用到再看
 * @param {*} arg  使用时传进来的mapStatetoProps
 * @param {*} factories  array[function, function]
 * 默认工厂defaultMapStateToPropsFactories, [whenMapStateToPropsIsFunction, whenMapStateToPropsIsMissing]
 * @param {*} name  string
 * @returns  function
 */
function match(arg, factories, name) {
  // 后到前遍历factories
  for (let i = factories.length - 1; i >= 0; i--) {
    // 调用factories, 返回值赋值给result, 去看 -> mapStateToProps.js
    const result = factories[i](arg)
    // result为true返回result, result为(dispatch, options) => function(){...}的function
    if (result) return result
  }
  // 不符合connect方法规则throw Error
  return (dispatch, options) => {
    throw new Error(
      `Invalid value of type ${typeof arg} for ${name} argument when connecting component ${
        options.wrappedComponentName
      }.`
    )
  }
}

// 判断对象的索引是否相同
function strictEqual(a, b) {
  return a === b
}

// 暴露createConnect, 想必肯定会返回function因为connect是个function
export function createConnect({
  // 一些带有默认值的参数, 我们看下面, 具体用到了在看👀
  connectHOC = connectAdvanced, // connectAdvanced(selectorFactory, [connectOptions])
  mapStateToPropsFactories = defaultMapStateToPropsFactories, // array[function, function]
  mapDispatchToPropsFactories = defaultMapDispatchToPropsFactories,
  mergePropsFactories = defaultMergePropsFactories,
  selectorFactory = defaultSelectorFactory
} = {}) {
  // 返回的connect function
  return function connect(
    // connect的四个可选参数
    mapStateToProps,
    mapDispatchToProps,
    mergeProps,
    // 配置参数
    {
      pure = true, // 是否就行浅比较的配置
      // 判断是否相同引用的function
      areStatesEqual = strictEqual, 
      // shallowEqual 详情看下面👇
      areOwnPropsEqual = shallowEqual,
      areStatePropsEqual = shallowEqual,
      areMergedPropsEqual = shallowEqual,
      // 其他配置项
      ...extraOptions
    } = {}
  ) {
    // mapStateToProps初始化
    const initMapStateToProps = match(
      // 使用时传递的mapStateToProps function
      mapStateToProps,
      // 默认值 -> 先看match方法, 然后我们来看mapStateToProps.js
      mapStateToPropsFactories,
      'mapStateToProps'
    )
    // mapDispatchToProps初始化
    const initMapDispatchToProps = match(
      mapDispatchToProps,
      mapDispatchToPropsFactories,
      'mapDispatchToProps'
    )
    // mergeProps的初始化
    const initMergeProps = match(mergeProps, mergePropsFactories, 'mergeProps')

    // return connectHOC function,将 React 组件连接到 Redux store 的函数
    // 先来看看他的参数
    // selectorFactory函数返回一个selector函数,根据store state, 展示型组件props,和dispatch计算得到新props,最后注入容器组件
    // selectorFactory  -> defaultSelectorFactory
    // 其实很熟悉react-redux api的同学应该很熟悉connectHOC的参数, 因为他就是connectAdvanced方法啊, 建议先看看api
    return connectHOC(selectorFactory, {
      // 用于错位信息
      methodName: 'connect',
      // 用Connect包装getDisplayName
      getDisplayName: name => `Connect(${name})`,
      // mapStateToProps是否为undefined,shouldHandleStateChanges为false则不监听store state
      shouldHandleStateChanges: Boolean(mapStateToProps),

      // selectorFactory需要的几个参数
      initMapStateToProps,     // (dispatch, options) => initProxySelector(dispatch, { displayName }){...}
      initMapDispatchToProps,
      initMergeProps,
      pure, // 默认true
      // strictEqual, 这里很容易想到用于判断this.state是不是都一份引用
      areStatesEqual,  
      // shallowEqual浅比较
      // 插个题外话,熟悉react PureComponent的同学应该可以快速反应过来!shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState)
      // 不熟悉的同学看过来 -> shallowEqual.js
      areOwnPropsEqual,  
      areStatePropsEqual,
      areMergedPropsEqual,
      // 容错处理, 其他的配置项
      ...extraOptions
    })
  }
}

// connect方法 直接调用createConnect
export default createConnect()


mapStateToProps.js

import { wrapMapToPropsConstant, wrapMapToPropsFunc } from './wrapMapToProps'

// 当mapStateToProps为function时调用wrapMapToPropsFunc
export function whenMapStateToPropsIsFunction(mapStateToProps) {
  return typeof mapStateToProps === 'function'
    // 看wrapMapToPropsFunc -> wrapMapToProps.js
    ? wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps')
    : undefined
}

// match中的数组倒着遍历先看这里
// 容错处理, 判断是否传递mapStateToProps参数
export function whenMapStateToPropsIsMissing(mapStateToProps) {
  // 如果传递了mapStateToProps参数且!mapStateToProps = true返回undefined,此时result为undefined,无效调用
  // 没有传递mapStateToProps参数或mapStateToProps=false -> wrapMapToPropsConstant
  return !mapStateToProps ? wrapMapToPropsConstant(() => ({})) : undefined
}

// export default是array,元素为function
export default [whenMapStateToPropsIsFunction, whenMapStateToPropsIsMissing]


/**
 * 小结:
 * 
 * mapstateToprops参数可执行时调用wrapMapToPropsFunc(mapStateToProps, 'mapStateToProps')
 * 不传递mapstateToprops参数时 wrapMapToPropsConstant(() => ({}))
 * 我们接着刨根问底 看->wrapMapToProps.js
 * 
 * * */

wrapMapToProps.js

import verifyPlainObject from '../utils/verifyPlainObject'

/**
 *
 * @export  mapstateToprops为undefined调用
 * @param {*} getConstant  () => ({})
 * @returns  function initConstantSelector(dispatch, options)
 */
export function wrapMapToPropsConstant(getConstant) {
  // 返回 initConstantSelector
  return function initConstantSelector(dispatch, options) {
    const constant = getConstant(dispatch, options) 

    function constantSelector() {
      return constant
    }
    constantSelector.dependsOnOwnProps = false
    return constantSelector
  }
}

// 用来判断是否存在ownProps 
// mapStateToProps(state, [ownProps])
export function getDependsOnOwnProps(mapToProps) {
  // 不是第一次调用直接返回Boolean
  return mapToProps.dependsOnOwnProps !== null &&
    mapToProps.dependsOnOwnProps !== undefined
    ? Boolean(mapToProps.dependsOnOwnProps)
    // 第一次调用时mapToProps的dependsOnOwnProps为undefined,直接判断参数个数
    : mapToProps.length !== 1  
}

/**
 * @export  mapstateToprops传递时调用
 * @param {*} mapToProps  使用connect是传递的mapStateToProprs
 * @param {*} methodName  名称  methodName = 'mapStatetoProps' || 'mapDispatchToProps'
 * @returns  返回initProxySelector(dispatch, { displayName })
 */
export function wrapMapToPropsFunc(mapToProps, methodName) {
  // 终于找到你!! 返回initProxySelector function, 这个返回值会赋值给initMapStateToProps(当然还有initDispatchToProps)
  return function initProxySelector(dispatch, { displayName }) {
    // 定义proxy function,且作为返回值
    const proxy = function mapToPropsProxy(stateOrDispatch, ownProps) {
      return proxy.dependsOnOwnProps  // mapStateToProps计算是否依赖组件的props
        ? proxy.mapToProps(stateOrDispatch, ownProps) //  返回proxy.mapToProps,继续看一下他是什么鬼👻
        : proxy.mapToProps(stateOrDispatch)
    }
    // dependsOnOwnProps标记运行依赖组件的props为true
    proxy.dependsOnOwnProps = true

    // detectFactoryAndVerify为返回的function
    // 梳理一下,目前调用链是这样的
    // const initMapStateToProps = initProxySelector(dispatch, { displayName })=>
    //                             mapToPropsProxy(stateOrDispatch, ownProps) => detectFactoryAndVerify(stateOrDispatch, ownProps)
    // detectFactoryAndVerify赋值给proxy.mapToProps
    // 第一次调用 mapToPropsProxy时返回detectFactoryAndVerify(stateOrDispatch, ownProps)
    proxy.mapToProps = function detectFactoryAndVerify(
      stateOrDispatch,
      ownProps
    ) {
      // 调用的时候 mapToPropsfunction 赋值给 proxy.mapToProps
      // 也就是第一次除了调用到proxy.mapToProps之后, 以后在调用到proxy.mapToProps的时候则使用传递的mapToProps function
      proxy.mapToProps = mapToProps
      // 重新判断 dependsOnOwnProps(第一次默认true)
      proxy.dependsOnOwnProps = getDependsOnOwnProps(mapToProps)
      // 定义props为proxy(stateOrDispatch, ownProps)
      // 先看下执行顺序 第一次调用initProxySelector() => proxy() => 
      // 此时 proxy.mapToProps = detectFactoryAndVerify()
      // 再次调用 proxy(stateOrDispatch, ownProps)时 返回值为传递的mapToProps(...args),也就是我们react组件需要的props
      let props = proxy(stateOrDispatch, ownProps)

      // 如果props为function再次执行
      if (typeof props === 'function') {
        proxy.mapToProps = props
        proxy.dependsOnOwnProps = getDependsOnOwnProps(props)
        props = proxy(stateOrDispatch, ownProps)
      }

      // 非production环境检查
      if (process.env.NODE_ENV !== 'production')
        // verifyPlainObject是utils方法, 如果不是纯对象,抛出warning
        verifyPlainObject(props, displayName, methodName)

      // 返回最终的props
      return props
    }

    return proxy
  }
}

mergeProps.js和mapDisptchToPtops.js同理,返回一个array[function,function],对参数做容错处理,返回一个initProxySelector function() => proxy => props, 具体细节后面介绍

shallowEqual

shallowEqual通常用来对object做浅比较,经常会出现在react应用中, 配合shouldComponentUpdate做性能优化, 如果熟悉PureComponent原理同学,那应该知道这段代码

!shallowEqual(instance.props, nextProps) || !shallowEqual(instance.state, nextState)

shallowEqual.js

// 对象自身属性中是否具有指定的属性
const hasOwn = Object.prototype.hasOwnProperty

// 判断两个值是否是相同的值
function is(x, y) {
   // SameValue algorithm
   if (x === y) { 
    return x !== 0 || y !== 0 || 1 / x === 1 / y;
  } else {
    return x !== x && y !== y;
  }
}

// 浅比较 只会比较到两个对象的 ownProperty 是否符合 Object.is 判等,不会递归地去深层比较
//    shallowEqual({x:{}},{x:{}}) // false
//    shallowEqual({x:1},{x:1}) // true
export default function shallowEqual(objA, objB) {
  // 相同值直接返回true,shallowEqual返回值为boolean
  if (is(objA, objB)) return true

  // 在objA和objB不是相同值的前提下, 如果objA,objB为null或非object可以判定返回false
  if (
    typeof objA !== 'object' ||
    objA === null ||
    typeof objB !== 'object' ||
    objB === null
  ) {
    return false
  }

  // 定义objA,objB的key数组
  const keysA = Object.keys(objA)
  const keysB = Object.keys(objB)

  // length不同说明object不同
  if (keysA.length !== keysB.length) return false

  // 循环遍历keysA
  for (let i = 0; i < keysA.length; i++) {
    // 如果objB不含有objA的key且objA与objB的value不同, 返回false
    if (!hasOwn.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
      return false
    }
  }

  // 如果通过了for循环, 说明objA, objB中的第一层key和value都相同,恭喜通过
  return true
}

connect总结

由于connect函数设计的方法过多,我们在这里简化一下connect的代码(以下为源码的精简伪代码)

  // 首先为以参数的形式为connect注入一些方法
export function createConnect({
 ...
  // connectAdvanced为react-redux暴露出的api
  connectHOC = connectAdvanced,
  ...
} = {}) {
  // connect方法
  return function connect(
    // 接受的四个参数
    mapStateToProps,
    mapDispatchToProps,
    mergeProps,
    {
      pure = true,  // 是否就行浅比较的配置
      strictEqual,  // 判断object引用, strictEqual(a, b)=> a === b
      shallowEqual, // 浅比较,上面介绍了
      ...extraOptions  // 其他配置项
    } = {}
  ) {
    // 一系列的方法执行,对三个参数的类型做了容错处理
    // 分别初始化了各自的参数mapStateToProps,mapDispatchToProps,mergeProps,注入了一些内部的默认参数和方法
    // 他们大致是这样的function: 
    // (dispatch, options) => initProxySelector() => mapToPropsProxy() => props
    const initMapStateToProps = match(...args)
    const initMapDispatchToProps = match(...args)
    const initMergeProps = match(...args)
    // 返回值由执行connectAdvanced获取,并传入初始化的initMapStateToProps等参数和pure等配置项
    return connectAdvanced(selectorFactory, {
      initMapStateToProps,
      initMapDispatchToProps,
      initMergeProps,
      pure,
      ...extraOptions
    })
  }
}

 // 直接执行createConnect方法返回connect
export default createConnect()

connectAdvanced高阶函数

从connect()(<A/ >)中不难看出connect的返回值为一个高阶组件,包装当前的react组件,返回一个增强props的组件,在执行connect时会执行connectAdvanced,接下来我们不得不看下connectAdvanced方法的实现,先介绍一下connectAdvanced -> 👀看注释

connectAdvanced.js

// hoist-non-react-statics组件,这个组件会自动把所有绑定在对象上的非React静态(static)方法都绑定到新的对象上
import hoistStatics from 'hoist-non-react-statics'
// 提示信息插件
import invariant from 'invariant'
import React, { Component, PureComponent } from 'react'
import { isValidElementType } from 'react-is'
// context
import { ReactReduxContext } from './Context'

/**
 *
 * @export  介绍下connectAdvanced
 *  connect() 的基础,真正将 React 组件连接到 Redux store 的函数
 * @param {*} selectorFactory function  selectorFactory(dispatch, factoryOptions)
 *  初始化选择器函数,该选择器函数是在 connector 组件需要重新计算一个新的 props 时调用
 *  作为 store 的 state 改变或者接收到一个新的 props 的结果。selector 的结果应该是一个普通对象,
 *  作为被包裹的组件的 props 传递。如果连续调用 selector 都返回与上一次调用相同的对象(===),
 *  则不会重新渲染该组件。selector 的责任是在适当的时候返回以前的对象。
 * @param {*} [{
 *     getDisplayName = name => `ConnectAdvanced(${name})`,  DisplayName
 *     methodName = 'connectAdvanced',
 *     renderCountProp = undefined,
 *     shouldHandleStateChanges = true,
 *     storeKey = 'store',
 *     withRef = false,
 *     context = ReactReduxContext,
 *     ...connectOptions
 *   }={}]
 * @returns
 */
export default function connectAdvanced(
   // function, 使用的时候在介绍selectorFactory.js
  selectorFactory,
  // options object:
  {
    // 被包裹的组件的 DisplayName 属性
    getDisplayName = name => `ConnectAdvanced(${name})`,
    // 用于显示错误消息
    methodName = 'connectAdvanced',
    // 组件是否订阅 redux store 的 state 更改
    shouldHandleStateChanges = true,
    renderCountProp = undefined, // 传递给内部组件的props键,表示render方法调用次数
    // 可以获取 store 的 props/context key
    storeKey = 'store',
    // 如果为 true,则将一个引用存储到被包裹的组件实例中,并通过 getWrappedInstance() 方法使其可用
    withRef = false,
    // 看到这个变量我的第一反应是ref的转发, 不了解的同学去看一下React.forwardRef()
    forwardRef = false,
    // provider的ReactReduxContext方法
    context = ReactReduxContext,
    ...connectOptions
  } = {}
) {
  // invariant 一个只在development环境的error
  // When process.env.NODE_ENV is not production, the message is required.
  // 这几个配置参数别使用的时候会有warnning,直接跳过这部分
  invariant(
    renderCountProp === undefined,
    `renderCountProp is removed. render counting is built into the latest React dev tools profiling extension`
  )

  invariant(
    !withRef,
    'withRef is removed. To access the wrapped instance, use a ref on the connected component'
  )

  const customStoreWarningMessage =
    'To use a custom Redux store for specific components,  create a custom React context with ' +
    "React.createContext(), and pass the context object to React-Redux's Provider and specific components" +
    ' like:  <Provider context={MyContext}><ConnectedComponent context={MyContext} /></Provider>. ' +
    'You may also pass a {context : MyContext} option to connect'

  invariant(
    storeKey === 'store',
    'storeKey has been removed and does not do anything. ' +
      customStoreWarningMessage
  )

  // 定义Context
  const Context = context

  // 返回react高阶组件,  WrappedComponent既包装的react组件
  return function wrapWithConnect(WrappedComponent) {
    // 参数检验
    if (process.env.NODE_ENV !== 'production') {
      invariant(
        isValidElementType(WrappedComponent),
        `You must pass a component to the function returned by ` +
          `${methodName}. Instead received ${JSON.stringify(WrappedComponent)}`
      )
    }

    // 组件的displayName,默认Component
    const wrappedComponentName =
      WrappedComponent.displayName || WrappedComponent.name || 'Component'

    // 拼接下displayName
    const displayName = getDisplayName(wrappedComponentName)

    // 定义selectorFactoryOptions对象,包含了connect和connectAdvanced的所有参数
    const selectorFactoryOptions = {
      // connectOptions为initMapStateToProps,initMapDispatchToProps,pure等参数
      ...connectOptions,
      getDisplayName,
      methodName,
      renderCountProp,
      shouldHandleStateChanges,
      storeKey,
      displayName,
      wrappedComponentName,
      WrappedComponent
    }

    // pure决定shouldComponentUpdate是否进行shwoEqual
    const { pure } = connectOptions

    // Component赋值给OuterBaseComponent, 用react高阶的继承
    let OuterBaseComponent = Component
    // 定义FinalWrappedComponent
    let FinalWrappedComponent = WrappedComponent

    if (pure) {
      // 为true用PureComponent
      OuterBaseComponent = PureComponent
    }
    // 接下来直接看 class Connect extends OuterBaseComponent

// 
function makeDerivedPropsSelector() {
      // 定义变量, 用来保存上一次makeDerivedPropsSelector中的值
      // 变量语义化我们不难猜出意义
      let lastProps
      let lastState
      let lastDerivedProps
      let lastStore
      let sourceSelector
      return function selectDerivedProps(state, props, store) {  // props为父组件的props
        // pure为true时,props和state的引用都没有变化, 直接返回lastDerivedProps(第一次肯定不会成立)
        // 这里不难理解, 就是要求你用"纯"的state和props
        if (pure && lastProps === props && lastState === state) {
          return lastDerivedProps
        }

        if (store !== lastStore) {
          // store赋值lastStore, 更新lastStore
          // 除第一次调用外一般不会
          lastStore = store
          // selectorFactory为connect传入的function,默认值来自selsctorFactory.js的export default
          sourceSelector = selectorFactory(
            store.dispatch,
            selectorFactoryOptions  // 所有参数集合
          )
        }

        // props赋值给lastProps
        lastProps = props
        // state赋值给lastState
        lastState = state

        // 调用sourceSelector参入redux state和props, 得到最新的props
        // 不难看出selectorFactory的返回值为一个function, 目前我们可以猜测到
        // selsctorFactory.js的export default function 大体结构是这样(dispatch, selectorFactoryOptions)=>(state, props) => newProps
        const nextProps = sourceSelector(state, props)

        // 新旧props引用相同
        if (lastDerivedProps === nextProps) {
          // 直接返回
          return lastDerivedProps
        }
        // 新旧props引用不相同, nextProps赋值给lastDerivedProps
        lastDerivedProps = nextProps
        // 返回lastDerivedProps
        return lastDerivedProps
        // 最后我们去看selsctorFactory.js到底如何合并的state和props
      }
    }

    function makeChildElementSelector() {
      // 定义props, ref, element变量
      let lastChildProps, lastForwardRef, lastChildElement
      // 返回function
      return function selectChildElement(childProps, forwardRef) {
        // 判断新旧props, hre, elelment是否相同
        if (childProps !== lastChildProps || forwardRef !== lastForwardRef) {
          // 如果不同重新赋值
          lastChildProps = childProps
          lastForwardRef = forwardRef
          lastChildElement = (
            // return FinalWrappedComponent, 改变props和ref
            <FinalWrappedComponent {...childProps} ref={forwardRef} />
          )
        }
        // react组件
        return lastChildElement
      }
    }

    class Connect extends OuterBaseComponent {
      constructor(props) {
        super(props)
        invariant(
          forwardRef ? !props.wrapperProps[storeKey] : !props[storeKey],
          'Passing redux store in props has been removed and does not do anything. ' +
            customStoreWarningMessage
        )
        // 添加selectDerivedProps和selectChildElement方法
        // selectDerivedProps为function是makeDerivedPropsSelector的返回值
        this.selectDerivedProps = makeDerivedPropsSelector()
        // selectChildElement为function
        this.selectChildElement = makeChildElementSelector()
        // bind this
        this.renderWrappedComponent = this.renderWrappedComponent.bind(this)
      }

      // value为context,既provider中的{storeState: store.getState(),store}
      renderWrappedComponent(value) {
        invariant(
          value,
          `Could not find "store" in the context of ` +
            `"${displayName}". Either wrap the root component in a <Provider>, ` +
            `or pass a custom React context provider to <Provider> and the corresponding ` +
            `React context consumer to ${displayName} in connect options.`
        )

        // 获取redux state和store
        const { storeState, store } = value

        // 定义wrapperProps为this.props
        let wrapperProps = this.props
        let forwardedRef
        // forwardRef为真时, Connect组件提供了forwardedRef = {ref}
        if (forwardRef) {
          // wrapperProps为props中的wrapperProps
          wrapperProps = this.props.wrapperProps
          // forwardedRef赋值为props的forwardedRef, 传递的是ref
          // 用于传递给子组件WrappedComponent既let FinalWrappedComponent = WrappedComponent中的FinalWrappedComponent
          forwardedRef = this.props.forwardedRef
        }

        // 导出props
        let derivedProps = this.selectDerivedProps(
          storeState,
          wrapperProps,
          store
        )

        // 返回最终的组件,传入最终的props和ref -> 看selectChildElement发放
        return this.selectChildElement(derivedProps, forwardedRef)
      }

      render() {
        // 默认情况下公用的ReactReduxContext
        const ContextToUse = this.props.context || Context

        return (
          // <Privoder />的消费者
          <ContextToUse.Consumer>
            {this.renderWrappedComponent}
          </ContextToUse.Consumer>
        )
      }
    }

    // 相当于插件
    // 包装的组件赋值给Connect.WrappedComponent
    Connect.WrappedComponent = WrappedComponent
    // 添加displayName
    Connect.displayName = displayName

    // forwardRef为true时
    if (forwardRef) {
      // 使用react.forwardRef为connect生成的组件的父组件提供孙子(传递给connect的组件)组件
      const forwarded = React.forwardRef(function forwardConnectRef(
        props,
        ref
      ) {
        return <Connect wrapperProps={props} forwardedRef={ref} />
      })

      // 此时connect()(<xx />)的生成组件为forwarded, 从新挂载displayName和WrappedComponent
      forwarded.displayName = displayName
      forwarded.WrappedComponent = WrappedComponent
      return hoistStatics(forwarded, WrappedComponent)
    }

    // 将子组件的非React的static(静态)属性或方法合并到父组件
    // 返回拓展过props属性的Connect组件
    return hoistStatics(Connect, WrappedComponent)
  }
}

connectAdvanced返回一个react高阶组件, 根据pure,forwardRef配置决定是否采用PureComponent和ref的转移, 通过selectDerivedProps放法生成最终的props,传递给最终返回的react组件,最后我们去看selsctorFactory.js到底如何合并的state和props

selectorFactory

selectorFactory函数返回一个selector函数,根据store state, 展示型组件props和dispatch计算得到新props,最后注入容器组件中

selectorFactory.js实现

import verifySubselectors from './verifySubselectors'

export function impureFinalPropsSelectorFactory(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps,
  dispatch
) {
  return function impureFinalPropsSelector(state, ownProps) {
    // 执行mergePropsProxy,返回修改后的props
    return mergeProps(
      mapStateToProps(state, ownProps),  // mapStateToProps执行结果
      mapDispatchToProps(dispatch, ownProps), // mapDispatchToProps的执行结果
      ownProps // 自身的props
    )
  }
}

export function pureFinalPropsSelectorFactory(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps,
  dispatch,
  // areStatesEqual判断是否是相同的引用
  // areOwnPropsEqual, areStatePropsEqual为shallowEqual
  { areStatesEqual, areOwnPropsEqual, areStatePropsEqual }
) {
  // hasRunAtLeastOnce标记第一次执行
  // 先看return的function,再看其他的function都做了什么
  let hasRunAtLeastOnce = false
  let state
  let ownProps
  let stateProps
  let dispatchProps
  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
    hasRunAtLeastOnce = true
    // 返回mergedProps
    return mergedProps
  }

  function handleNewPropsAndNewState() {
    // 获取当前新的的state
    stateProps = mapStateToProps(state, ownProps)

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

    // 返回mergedProps function内部为新的object
    mergedProps = mergeProps(stateProps, dispatchProps, ownProps)
    return mergedProps
  }

  // 自身props改变
  function handleNewProps() {
    // dependsOnOwnProps之前介绍过,判断是否有第一个参数ownprops
    // 如果存在需要重新执行,获取新的stateProps和mapDispatchToProps,因为自身的props改变了
    if (mapStateToProps.dependsOnOwnProps)
      stateProps = mapStateToProps(state, ownProps)

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

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

  // redux state改变
  function handleNewState() {
    const nextStateProps = mapStateToProps(state, ownProps)
    // 浅比较nextStateProps和stateProps
    const statePropsChanged = !areStatePropsEqual(nextStateProps, stateProps)
    // 更新stateProps
    stateProps = nextStateProps

    //statePropsChanged为ture,浅比较失败,mergedProps需要重新计算,mergedProps返回新对象
    if (statePropsChanged)
      mergedProps = mergeProps(stateProps, dispatchProps, ownProps)

    return mergedProps
  }

  function handleSubsequentCalls(nextState, nextOwnProps) {
    // 执行的时候ownProps浅比较
    const propsChanged = !areOwnPropsEqual(nextOwnProps, ownProps)
    // 比较redux state的引用
    const stateChanged = !areStatesEqual(nextState, state)
    // nextState赋值给state
    state = nextState
    // nextOwnProps赋值给onwProps
    ownProps = nextOwnProps

    // props && state change
    // 看不同情况对应的return function
    if (propsChanged && stateChanged) return handleNewPropsAndNewState()
    // props change
    if (propsChanged) return handleNewProps()
    // state change
    if (stateChanged) return handleNewState()
    // propsChanged, stateChanged为true认为props,state没有改变,return mergedProps
    return mergedProps
  }

  return function pureFinalPropsSelector(nextState, nextOwnProps) {  // state props
    return hasRunAtLeastOnce // 默认值为false
      ? handleSubsequentCalls(nextState, nextOwnProps)
      : handleFirstCall(nextState, nextOwnProps)
  }
}

// 找到export default
/**
 *
 *
 * @export
 * @param {*} dispatch // store.dispatch
 * @param {*} { 
 *    initMapStateToProps // 结构initProxySelector(dispatch, { displayName }) => proxy
 *    initMapDispatchToProps, // 结构 initMergePropsProxy(dispatch, options) => mergePropsProxy 
 *    initMergeProps, 
 *    ...options    其他配置
 *  }
 * @returns  selectorFactory function 
 */
// finalPropsSelectorFactory和我们的设想结构一致
export default function finalPropsSelectorFactory(
  dispatch,
  
  { initMapStateToProps, initMapDispatchToProps, initMergeProps, ...options }
) {
  // 调用initProxySelector得到proxy function, proxy包含mapToProps, dependsOnOwnProps属性
  const mapStateToProps = initMapStateToProps(dispatch, options)
  const mapDispatchToProps = initMapDispatchToProps(dispatch, options)
  // mergePropsProxy为function
  // 返回值为connect(mapstate,mapdispatch,function mergeProps(){})()中mergeProps的返回值
  const mergeProps = initMergeProps(dispatch, options)

  // 非production环境检验 mapStateToProps,mapDispatchToProps,mergeProps
  if (process.env.NODE_ENV !== 'production') {
    verifySubselectors(
      mapStateToProps,
      mapDispatchToProps,
      mergeProps,
      options.displayName
    )
  }

  // pure为true时表示selectorFactory的返回值缓存, 根据当前的redux state和ownProps的变化尽量做最出小的改变
  // 详情看pureFinalPropsSelectorFactory
  // 否则返回新对象
  const selectorFactory = options.pure
    ? pureFinalPropsSelectorFactory
    : impureFinalPropsSelectorFactory

  // 执行selectorFactory
  // selectorFactory为工厂函数,返回selector
  return selectorFactory(
    mapStateToProps,
    mapDispatchToProps,
    mergeProps, // function mergePropsProxy
    dispatch,
    options
  )
}

mergedProps实现

import verifyPlainObject from '../utils/verifyPlainObject'

export function defaultMergeProps(stateProps, dispatchProps, ownProps) {
  // 返回一个新对象
  return { ...ownProps, ...stateProps, ...dispatchProps }
}

export function wrapMergePropsFunc(mergeProps) {
  // initMergeProps
  return function initMergePropsProxy(
    dispatch,
    { displayName, pure, areMergedPropsEqual }
  ) {
    // 第一次运行,设置为false
    let hasRunOnce = false
    let mergedProps

    return function mergePropsProxy(stateProps, dispatchProps, ownProps) {
      // mergeProps的返回结果
      const nextMergedProps = mergeProps(stateProps, dispatchProps, ownProps)

      if (hasRunOnce) {
        // pure为fales 或者mergedProps为null
        if (!pure || !areMergedPropsEqual(nextMergedProps, mergedProps))
          mergedProps = nextMergedProps
      } else {
        // 不是第一次运行,hasRunOnce标记为false
        hasRunOnce = true
        // nextMergedProps赋值给mergedProps
        mergedProps = nextMergedProps

        if (process.env.NODE_ENV !== 'production')
          verifyPlainObject(mergedProps, displayName, 'mergeProps')
      }

     // 返回修改后的props
      return mergedProps
    }
  }
}

export function whenMergePropsIsFunction(mergeProps) {
  // 如果mergeProps为true且是function, 调用wrapMergePropsFunc返回function initMergePropsProxy(){}
  return typeof mergeProps === 'function'
    ? wrapMergePropsFunc(mergeProps)
    : undefined
}

export function whenMergePropsIsOmitted(mergeProps) {
  // mergeProps !== true retun () => { ...ownProps, ...stateProps, ...dispatchProps }
  return !mergeProps ? () => defaultMergeProps : undefined
}

// 后向前执行
export default [whenMergePropsIsFunction, whenMergePropsIsOmitted]

/**
 * [mergeProps(stateProps, dispatchProps, ownProps): props] (Function):
 *  如果指定了这个参数,mapStateToProps() 与 mapDispatchToProps() 的执行结果和组件自身的 props 将传入到这个回调函数中。
 *  该回调函数返回的对象将作为 props 传递到被包装的组件中
 */