编写一个react-redux的connect

176 阅读2分钟

概述

众所周知,react-redux只是帮忙管理一下redux的store。

react-redux 有两个重要组成:Provider 和 connect。

  • Provider 接收store作为props,然后通过context往下传递,以至任何组件都能获取store。

  • connect 作为高阶组件对原有组件进行强化,接收两个参数,mapStateToProps 和 mapDispatchToProps。

    mapStateToProps 自动接收state,mapDispatchToProps 自动接收dispatch。

    前者是一个方法(返回一个对象),后者是一个对象(里面包含dispatch方法)。

调用connect之后,react-redux就会帮助我们进行store的操作。把我们写的属性,方法,还有父组件的传值传入我们要强化的组件的props。

在redux里面,我们也可以用store.getState( ) , store.dispatch( )直接进行store操作。

照着这个逻辑,就可以仿写一下connect了。

代码

import store from '../../store';

class Com extends Component {
  render() {
    return (
        <div>
          <button onClick={this.props.minus}>-</button>
        </div>
    )
  }
}

function connectFun(callback,obj){
  var value = callback()    //执行传入的mapStateToProps得到值
  return (MyComponent)=>{   //将传入的组件作为参数调用
    return  (props)=>{      //获取父组件传入的值
      return <div>  
        {/* 将父组件传入的和传入的两个参数一起传给要强化的组件 */}
        <MyComponent {...value} {...obj} {...props} ></MyComponent>    
      </div>
    } 
  }
}

const mapStateToProps = () =>{
    let store_state = store.getState()
    return {
      ...store_state
    }
}

const mapDispatchToProps = {
    minus:()=>{
      store.dispatch({
          type:'minus_action'
      })
    }    
}   
export default connectFun( mapStateToProps ,  mapDispatchToProps )(Com)

这里的第一步直接引入了store进行操作。

Provider 为了每个组件都能访问store,通过context传递,那我们能不能在context里面直接取得store就不用引入了呢?

但是我后面怎么找都找不到,看看它的源码:

import { Component, Children } from 'react'
    import PropTypes from 'prop-types'
    import storeShape from '../utils/storeShape'
    import warning from '../utils/warning'

    export default class Provider extends Component {
      getChildContext() {
        return { store: this.store }
      }
        
      constructor(props, context) {
        super(props, context)
        this.store = props.store
      }
    
      render() {
        return Children.only(this.props.children)
      }
    }

getChildContext 之后就不知道去哪了。

既然取不到store,那把Provider一块删了吧。

最后可以把这个 connectFun 封装一下,把store作为一个参数,这样就不用每次引入了,只需引入这个封装的方法,和原始引入的 import { connect } from 'react-redux' 一样。

感想

这个connect高阶组件好像proxy代理,可以对另一个组件进行数据的拦截,中途插入一些操作。