实现一个react-redux的connect函数

1,028 阅读2分钟

我正在参加「掘金·启航计划」

我们在使用redux的时候,经常会使用到react-redux库里面的connect,他接受两个参数,返回值也是一个函数,并接收一个组件,实现组件与redux的结合。他的实现原理很简单,这篇文章将实现一个自定义connect函数,并具备react-redux的connect的功能。

  • 首先需要定义一个connect函数,并接收两个参数:mapStateToProps与mapActionToProps。
    • mapStateToProps可以理解为需要从redux中订阅哪些数据。
    • mapActionToProps可以理解为需要如何修改redux中的数据。
  • 在组件的构造函数construct中使用matStateToProps函数将需要的数据从redux获取,并为组件提供一个初始化状态。
  • 在组件挂载完毕后,订阅redux中的数据,当redux中的数据被修改时,会触发subscribe函数,并执行组件的setState方法,完成组件状态的更新以及页面的重新渲染。
  • 组件的render部分,需要将mapStateToProps获取到的redux状态,mapActionToProps处理后的修改redux的store的方法,以及其他参数,传递给组件。
  • 最后在组件的销毁时,取消订阅redux,防止内存泄露。
import { StoreContext } from './context';

// 定义一个connect函数,并接收两个参数
export const connect = function (mapStateToProps, mapActionToProps) {
  // 返回值是一个函数,接收一个组件,并返回一个组件
  return function (Cpn) {
    class WraperCpn extends PureComponent {
      static contextType = storeContext;
      constructor(props, context) {
        super(props, context);
        // 在组件创建的时候,初始化组件状态数据
        this.storeState = mapStateToProps(context);
      }
      componentDidMount() {
        // 在组件挂载后,订阅redux中的数据
        this.unsubscribe = this.context.subscribe(() => {
          this.setState({
            storeState: mapStateToProps(this.context)
          })
        })
      }

      componentWillUnmount() {
        // 在组件销毁的时候,取消组件订阅的redux
        this.unsubscribe();
      }

      render() {
        return <Cpn
          {...this.props}
          {...mapStateToProps(this.context)}
          {...mapActionToProps(this.context.dispatch)}></Cpn>
      }
    }
    return WraperCpn;
  }
}

mapStateToPropsmapDispatchToProps

这俩函数通常是这种格式,mapStateToProps接收redux的store,返回组件所需的状态数据。mapDispatchToProps通常接收redux的dispatch方法,执行状态变更的相关操作。

const mapStateToProps = state => ({
  counter: state.counter
})

const mapDispatchToProps = dispatch => ({
  increment() {
    dispatch(incAction());
  },
  addNumber(num) {
    dispatch(addAction(num));
  }
})

为了使该connect更具有拓展性,在自定义connect中,我们导入了一个context.js,他提供了一个context,是为了在外部传递store数据给connect。到这里就实现了react-redux的connect函数。

context.js

import React from 'react';

const StoreContext = React.createContext(); 

export {
  StoreContext
}

通过StoreContext.Provider就可以将store传递给使用了自定义connect函数的子组件

import React from 'react';
import ReactDOM from 'react-dom';

import store from './store';

import { StoreContext } from './utils/context';

import App from './App';

ReactDOM.render(
  <StoreContext.Provider store={store}>
    <App />
  </StoreContext.Provider>,
  document.getElementById('root')
);

点赞收藏不迷路