react-redux的connect方法通过高阶组件去实现

//connect功能
// 1,接受一个组件,把数据放到组件内部,返回一个组件
// 2,数据发生变化的时候,通知到组件

  //高阶组件实现connect

// 接受两个参数,防止不传报错需要预设默认值,
// 第一个参数是函数,来确定到底返回什么属性,默认原样返回(state=>state),
// 第二个是actionCreator的集合,是一个对象, 默认是个空对象
//两次函数嵌套把return 能省的都省了
export const connect=(mapStateToProps=state=>state,mapDispatchToProps={})=>(WrapComponent)=>(
        //直接返回一个高阶组件
         class ConnectComponent extends React.Component{
             //必须定义接受全局的store的类型  provider组件提供
            static contextTypes={
                store:PropTypes.object
            };
            constructor(props,context){
                super(props,context);

                this.state={
                    props:{}
                }

            }
            //组件初始化完成之后,把store里面的内容注入到props里;
            componentDidMount(){
                const {store}=this.context;
                //subscribe接受一个函数;我们当前函数就是 去执行this.update()调用,来达到更新;
                // 我们只要dispatch的动作,就会全部执行一遍subscribe的函数,来更新一遍数据;
                store.subscribe(()=>this.update());
              this.update();
            }
            //获取mapStateToProps和mapDispatchToProps;放入到props里;
            update(){
                //定义dispatch每个actionCreator的工具函数
                function bindActionCreator(creator,dispatch) {
                    //透传;就是如果creator有设置参数,直接通通...args解构掉,传过去;
                    return (...args)=>dispatch(creator(...args))
                }
                //定义dispatch过后每个actionCreator的对象集合工具函数
                function bindActionCreators(creators,dispatch) {
                    let obj={};
                  //用对象的每个key名生成数组循环;用每一个key名去 作用到相关的对象;
                  Object.keys(creators).forEach(v=>{
                      //拿到对象里每个键值对的值 ,也就是actionCreator函数
                       let creator=creators[v];
                     //重新生成的obj的每一项就都是被dispatch过的actionCreator;
                      obj[v]=bindActionCreator(creator,dispatch);
                  });
                    return obj;
                }

                //拿到公共上下文的store;
                const {store}=this.context;

                //store.getState()当前调用了拿到state;然后根据mapStateToProps的解构规则;返回state的对应值---stateProps;

                const stateProps=mapStateToProps(store.getState());

                // 把mapDispatchToProps用dispatch调用一下来传入的actionCreator对象里的每一个方法;用bindActionCreators实现
                const dispatchProps=bindActionCreators(mapDispatchToProps,store.dispatch);

                //这样就把stateProps,dispatchProps 注入进 props ,并且触发渲染;
                this.setState({props:{...this.state.props,...dispatchProps,...stateProps}});

            }
                render(){
                    return <WrapComponent {...this.state.props}  />
                }
   }
);




//这种写法比较繁琐,所以更推荐上面的两层箭头函数嵌套的写法,更加精炼
// export function connect(mapStateToProps=state=>state,mapDispatchToProps={}) {
//     return function (WrapComponent) {
//         return class ConnectComponent extends React.Component{
//             render(){
//                 return <WrapComponent/>
//             }
//         }
//     }
// }

其中,bindActionCreators 函数可以写成更加精简 通过强大的reduce数组处理函数


  //定义dispatch过后每个actionCreator的对象集合工具函数
        function bindActionCreators(creators,dispatch) {
          //   let obj={};
          // //用对象的每个key名生成数组循环;用每一个key名去 作用到相关的对象;
          // Object.keys(creators).forEach(v=>{
          //     //拿到对象里每个键值对的值 ,也就是actionCreator函数
          //      let creator=creators[v];
          //    //重新生成的obj的每一项就都是被dispatch过的actionCreator;
          //     obj[v]=bindActionCreator(creator,dispatch);
          // });
          //   return obj;


     //直接返回这个累加以后的结果,初始值是{},
     //reduce方法,入2个参数,第一个参数是回调函数,第二个函数是自重结果的初始值;
// 回调函数的入参 可以入4个参数;第一个参数是 计算的返回值(初始值===,reduce入的第二个参数),第二个参数是当前元素;
           return Object.keys(creators).reduce((rel,item)=>{
               rel[item]=bindActionCreator(creators[item],dispatch)
               return  rel;
           },{})
        }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值