聊聊redux的connect

724 阅读2分钟

connect作为高阶组件可以传入四个参数

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])

1.mapStateProps:本身是一个function:

          [mapStateToProps(state, [ownProps]): stateProps] (Function)

         例如:

connect(
(state)=>{     
user:state.user  //允许我们将store中的数据(state.user)作为props(user)绑定到组件中
})

this.props.user//页面组件读取store中state.user值

2.mapDispatchToProps:本身可以是一个object或function:

       [mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function)

     允许我们将 action 作为 props 绑定到组件中,如果传递的是一个对象,那么每个定义在         该对象的函数都将被当作 Redux action creator,对象所定义的方法名将作为属性名;

    每个方法将返回一个新的函数,函数中 dispatch 方法会将 action creator 的返回值作为参       数执行。这些属性会被合并到组件的 props 中。bindActionCreators() 可以自动把多个            action 创建函数 绑定到 dispatch() 方法上。

connect(state => ({     
   global: state.global, 
   user: state.user
}),
 dispath => ({ 
   actions: bindActionCreators(Actions, dispath)})
)(Real)


//this.props.xxactionsmethods页面组件dispatch action methods
或者
connect(state => ({     
   global: state.global, 
   user: state.user
}),
 (dispath)=> ({ 
        xxactionsmethods: payload => {
         dispatch({              
                type: 'amortization/query',   
             payload,
          })}
)(Real)

//this.props.xxactionsmethods页面组件dispatch action methods

3.mergeProps也是一个function:

[mergeProps(stateProps, dispatchProps, ownProps): props] (Function)

如果指定了这个参数,mapStateToProps()mapDispatchToProps() 的执行结果和组件自身的 props 将传入到这个回调函数中。该回调函数返回的对象将作为 props 传递到被包装的组件中。你也许可以用这个回调函数,根据组件的 props筛选部分的 state 数据,或者把 props 中的某个特定变量与 action creator 绑定在一起。如果你省略这个参数,默认情况下返回 Object.assign({}, ownProps, stateProps, dispatchProps) 的结果。

4.options

[options] (Object)
如果指定这个参数,可以定制 connector 的行为。

原理解析

connect之所以会成功,是因为Provider组件:

  • 在原应用组件上包裹一层,使原来整个应用成为Provider的子组件
  • 接收Redux的store作为props,通过context对象传递给子孙组件上的connect

它真正连接 Redux 和 React,它包在我们的容器组件的外一层,它接收上面 Provider 提供的 store 里面的 state 和 dispatch,传给一个构造函数,返回一个对象,以属性形式传给我们的容器组件。

源码

connect是一个高阶函数,首先传入mapStateToProps、mapDispatchToProps,然后返回一个生产Component的函数(wrapWithConnect),然后再将真正的Component作为参数传入wrapWithConnect,这样就生产出一个经过包裹的Connect组件

export default function connect(mapStateToProps, mapDispatchToProps, mergeProps, options = {}) {
  return function wrapWithConnect(WrappedComponent) {
    class Connect extends Component {
      constructor(props, context) {
        // 从祖先Component处获得store
        this.store = props.store || context.store
        this.stateProps = computeStateProps(this.store, props)
        this.dispatchProps = computeDispatchProps(this.store, props)
        this.state = { storeState: null }
        // 对stateProps、dispatchProps、parentProps进行合并
        this.updateState()
      }
      shouldComponentUpdate(nextProps, nextState) {
        // 进行判断,当数据发生改变时,Component重新渲染
        if (propsChanged || mapStateProducedChange || dispatchPropsChanged) {
          this.updateState(nextProps)
            return true
          }
        }
        componentDidMount() {
          // 改变Component的state
          this.store.subscribe(() = {
            this.setState({
              storeState: this.store.getState()
            })
          })
        }
        render() {
          // 生成包裹组件Connect
          return (
            <WrappedComponent {...this.nextState} />
          )
        }
      }
      Connect.contextTypes = {
        store: storeShape
      }
      return Connect;
    }
  }