首页 > 代码库 > Redux-react connect 的源码从新写了一遍

Redux-react connect 的源码从新写了一遍

import Counter from ‘../components/Counter‘;
import { increment, decrement, incrementIfOdd, incrementAsync } from ‘../actions‘;
import { bindActionCreators } from ‘redux‘;
import React, { Component, createElement } from ‘react‘;
import PropTypes from ‘prop-types‘;
import hoistStatics from ‘hoist-non-react-statics‘
import * as ActionCreators from ‘../actions‘;

const storeShape = PropTypes.shape({
  subscribe: PropTypes.func.isRequired,
  dispatch: PropTypes.func.isRequired,
  getState: PropTypes.func.isRequired
});

const connect = function(mapStateToProps, mapDispatchToProps){
    return function(WrappedComponent){
        class Connect extends Component {
            constructor(props, context) {
              super(props, context)
              this.store = props.store || context.store;

              const storeState = this.store.getState()
              this.state = { storeState }
            }

            handleChange() {
              const storeState = this.store.getState();
              this.setState({ storeState });
            }

            trySubscribe() {
                this.store.subscribe(this.handleChange.bind(this))
                this.handleChange();
            }

            componentDidMount() {
                this.trySubscribe();
            }

            render() {
                let store =  this.store;
                let dispatch = store.dispatch;
                let mergedProps = {};
                
                let dispatchProps;
                // 若它是个函数
                if (typeof mapDispatchToProps == ‘function‘){
                    dispatchProps = mapDispatchToProps;
                } else if(!mapDispatchToProps){
                    // 若没有传递参数
                    dispatchProps = dispatch => ({ dispatch });
                } else {
                    // 若 mapDispatchToProps 是一个对象
                    const wrapActionCreators = function(actionCreators) {
                      return function (dispatch) {
                        return bindActionCreators(actionCreators, dispatch);
                      };
                    }
                    dispatchProps = wrapActionCreators(mapDispatchToProps);
                    
                    // 若它是个对象, 属性值 是一个action create, 类似
                    // for(let j in mapDispatchToProps){
                    //     dispatchProps[j] = () => {
                    //         dispatch(mapDispatchToProps[j]());
                    //     }
                    // }
                }
                dispatchProps = dispatchProps(dispatch);
                
                let stateProps = mapStateToProps( this.state.storeState );
                for(let i in stateProps){
                    mergedProps[i] = stateProps[i];
                }

                for(let i in dispatchProps){
                    mergedProps[i] = dispatchProps[i];
                }

                return createElement(WrappedComponent,
                    mergedProps
                );
            }
        }

        Connect.contextTypes = {
          store: storeShape
        }
        Connect.propTypes = {
          store: storeShape
        }
        return hoistStatics(Connect, WrappedComponent);
    }
}

export default connect(
  state => ({ counter: state.counter }),
  /*
      注意这里写成如下形式不会被执行
      dispatch => ({
        increment: increment,
        decrement: decrement,
        incrementIfOdd: incrementIfOdd,
        incrementAsync: incrementAsync,
      })
  */
  // dispatch => ({
  //   increment: () => dispatch( increment() ),
  //   decrement: () => dispatch( decrement() ),
  //   incrementIfOdd: () => dispatch( incrementIfOdd() ),
  //   incrementAsync: () => dispatch( incrementAsync() )
  // })
  // ActionCreators
  dispatch => bindActionCreators(ActionCreators, dispatch)
)(Counter);

 

Redux-react connect 的源码从新写了一遍